text: #!/usr/bin/env python
  
  import os
  from os.path import dirname, abspath, basename
  import sys
  import argparse
  import json
  import subprocess
  import shutil
  import stat
  
  ROOT = abspath(dirname(dirname(dirname(dirname(__file__)))))
  sys.path.insert(0, ROOT)
  
  import examples_lib as lib
  from examples_lib import SUPPORTED_TOOLCHAINS
  
  def run_cmd(command, print_warning_on_fail=True):
      """ Takes the command specified and runs it in a sub-process, obtaining the return code.
          
      Args:
      command - command to run, provided as a list of individual fields which are combined into a 
                single command before passing to the sub-process call.
      return_code - result of the command.
  
      """
      print('[Exec] %s' % ' '.join(command))
      return_code = subprocess.call(command)
      
      if return_code:
          print("The command '%s' failed with return code: %s" % (' '.join(command), return_code))
          print("Ignoring and moving on to the next example")
      
      return return_code
      
  
  def rmtree_readonly(directory):
      """ Deletes a readonly directory tree.
          
      Args:
      directory - tree to delete
      """
      def remove_readonly(func, path, _):
          os.chmod(path, stat.S_IWRITE)
          func(path)
  
      shutil.rmtree(directory, onerror=remove_readonly)
  
  def find_all_examples(path):
      """ Searches the path specified for sub-example folders, ie those containing an
          mbed-os.lib file. If found adds the path to the sub-example to a list which is 
          then returned.
          
      Args:
      path - path to search.
      examples - (returned) list of paths to example directories.
  
      """
      examples = []
      for root, dirs, files in os.walk(path):
          if 'mbed-os.lib' in files:
              examples += [root]
      
      return examples
  
  def upgrade_single_example(example, tag, directory):
      """ Updates the mbed-os.lib file in the example specified to correspond to the 
          version specified by the GitHub tag supplied. Also deals with 
          multiple sub-examples in the GitHub repo, updating them in the same way.
          
      Args:
      example - json example object containing the GitHub repo to update.
      tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
      directory - directory path for the example.
      returns - True if the upgrade was successful, False otherwise.
      
      """
      print("Upgrading single example at path '%s'" % directory)
      cwd = os.getcwd()
      os.chdir(directory)
      
      return_code = None
      
      # Change directories to the mbed-os library
      if not os.path.exists('mbed-os'):
          print("'mbed-os' directory not found in the root of '%s'" % directory)
          print("Ignoring and moving on to the next example")
          os.chdir(cwd)
          return False
      
      os.chdir('mbed-os')
      
      # Setup and run the update command
      update_cmd = ['mbed', 'update', tag]
      return_code = run_cmd(update_cmd)
      
      if return_code:
          os.chdir(cwd)
          return False
      
      os.chdir('../')
      
      # Setup and run the add command
      add_cmd = ['git', 'add', 'mbed-os.lib']
      return_code = run_cmd(add_cmd)
      
      os.chdir(cwd)
      return not return_code
  
  def upgrade_example(example, tag):
      """ Clones the example specified from GitHub and updates the associated mbed-os.lib file
          to correspond to the version specified by the GitHub tag supplied. Also deals with 
          multiple sub-examples in the GitHub repo, updating them in the same way.
          
      Args:
      example - json example object containing the GitHub repo to update.
      tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
      
      """
      print("Updating example '%s'" % example['name'])
      cwd = os.getcwd()
      
      # Setup and run the import command
      clone_cmd = ['git', 'clone', example['github']]
      return_code = run_cmd(clone_cmd)
      
      if return_code:
          return False
      
      # Find all examples
      example_directories = find_all_examples(example['name'])
      
      os.chdir(example['name'])
      
      # Setup and run the update command
      import_cmd = ['mbed', 'update']
      return_code = run_cmd(import_cmd)
      if return_code:
          os.chdir(cwd)
          return False
      
      for example_directory in example_directories:
          if not upgrade_single_example(example, tag, os.path.relpath(example_directory, example['name'])):
              os.chdir(cwd)
              return False
          
      # Setup the default commit message
      commit_message = 'Updating mbed-os to {{' + tag +'}}'
              
      # Setup and run the commit command
      commit_cmd = ['git', 'commit', '-m', commit_message]
      return_code = run_cmd(commit_cmd)
      if return_code:
          if return_code == 1:
              print("[WARNING] 'git commit' exited with a return code of 1. " + \
              "This usually inidicates that no update was made. Still " + \
              "attempting to create a tag.")
          else:
              os.chdir(cwd)
              return False
      
      # Setup and run the tag command
      tag_cmd = ['git', 'tag', '-a', tag, '-m', tag]
      return_code = run_cmd(tag_cmd)
      if return_code:
          os.chdir(cwd)
          return False
      
      # Setup and run the push command
      push_cmd = ['git', 'push', 'origin', 'master']
      return_code = run_cmd(push_cmd)
      
      if return_code:
          os.chdir(cwd)
          return False
          
      push_cmd = ['git', 'push', 'origin', tag]
      return_code = run_cmd(push_cmd)
      
      os.chdir(cwd)
      return not return_code
  
  def create_work_directory(path):
      """ Create a new directory specified in 'path', overwrite if the directory already 
          exists.
          
      Args:
      path - directory path to be created. 
      
      """
      if os.path.exists(path):
          print("'%s' directory already exists. Deleting..." % path)
          rmtree_readonly(path)
      
      os.makedirs(path)
  
  def test_compile(config, tag):
      """ For each example repo identified in the config json object, clone, update mbed-os to
          the specified tag and then compile for all supported toolchains.
          
      Args:
      config - the json object imported from the file. 
      tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
      results - summary of compilation results. 
      
      """
      # Create work directories
      create_work_directory('test_compile')
      
      # Loop through the examples
      results = {}
      os.chdir('test_compile')
  
      lib.source_repos(config)    
      lib.update_mbedos_version(config, tag)
      results = lib.compile_repos(config, SUPPORTED_TOOLCHAINS)
      os.chdir("..")
  
      return results
      
  
  def main(arguments):
  
      parser = argparse.ArgumentParser(description=__doc__,
                                       formatter_class=argparse.RawDescriptionHelpFormatter)
      parser.add_argument('tag', help="mbed-os tag to which all examples will be updated")
      parser.add_argument('-c', '--config_file', help="Path to the configuration file (default is 'examples.json')", default='examples.json')
      
      args = parser.parse_args(arguments)
  
      cfg = os.path.join(os.path.dirname(__file__), args.config_file)
      
      # Load the config file
      config = json.load(open(os.path.join(os.path.dirname(__file__),
                               args.config_file)))
      
      if not config:
          print("Failed to load config file '%s'" % args.config_file)
          sys.exit(1)
      
      # Create work directories
      create_work_directory('examples')
      
      # Loop through the examples
      failures = []
      successes = []
      not_compiled = []
      results = {}
      os.chdir('examples')
  
      results = test_compile(config, args.tag)
      lib.print_compilation_summary(results)
      
      for example in config['examples']:
          # Determine if this example should be updated
  
          # Attempt to update if:
          #   group of examples passed compilation and
          #   auto update is set to True
          # Note: results fields are [compiled flag, pass flag, successes list, failures list]
          if not results[example['name']][0]:
              # Example was not compiled
              not_compiled += [example['name']]
          else:
              if results[example['name']][1] and example['auto-update']: 
                  if upgrade_example(example, args.tag):
                      successes += [example['name']]
                  else:
                      failures += [example['name']]
              else:    
                  failures += [example['name']]
      
      os.chdir('../')
      
      # Finish the script and report the results
      print(os.linesep + os.linesep +'Finished updating examples!' + os.linesep)
      
      if successes:
          print('The following examples updated successfully:')
          for success in successes:
              print('    - %s' % success)
      
      if failures:
          print('\nThe following examples were not updated:')
          for fail in failures:
              print('    - %s' % fail)
  
      if not_compiled:
          print('The following examples were skipped:')
          for example in not_compiled:
              print('    - %s' % example)
  
  
  if __name__ == '__main__':
      sys.exit(main(sys.argv[1:]))