| #!/usr/bin/env python |
| # Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| """Helper for building and deploying Observatory""" |
| |
| import argparse |
| import os |
| import platform |
| import shutil |
| import socket |
| import subprocess |
| import sys |
| import utils |
| |
| SCRIPT_DIR = os.path.dirname(sys.argv[0]) |
| DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..')) |
| PUB_PATH = os.path.join(DART_ROOT, 'third_party', 'pkg', |
| 'pub', 'bin', 'pub.dart') |
| IGNORE_PATTERNS = shutil.ignore_patterns( |
| '*.map', |
| '*.concat.js', |
| '*.scriptUrls', |
| '*.precompiled.js', |
| 'bower.json', |
| 'package.json', |
| 'CustomElements.*', |
| 'dart_support.*', |
| 'interop_support.*', |
| 'HTMLImports.*', |
| 'MutationObserver.*', |
| 'ShadowDOM.*', |
| 'webcomponents.*', |
| 'webcomponents-lite.js', |
| 'unittest*', |
| '*_buildLogs*', |
| '*.log', |
| '*~') |
| |
| usage = """observatory_tool.py [options]""" |
| |
| def DisplayBootstrapWarning(): |
| print """\ |
| |
| WARNING: Your system cannot run the checked-in Dart SDK. Using the |
| bootstrap Dart executable will make debug builds slow. |
| Please see the Wiki for instructions on replacing the checked-in Dart SDK. |
| |
| https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools |
| |
| To use the dart_bootstrap binary please update the PubCommand function |
| in the tools/observatory_tool.py script. |
| |
| """ |
| |
| def DisplayFailureMessage(): |
| print """\ |
| |
| ERROR: Observatory failed to build. What should you do? |
| |
| 1. Revert to a working revision of the Dart VM |
| 2. Contact zra@, johnmccutchan@, dart-vm-team@ |
| 3. File a bug: https://github.com/dart-lang/sdk/issues/new |
| |
| """ |
| |
| # Run |command|. If its return code is 0, return 0 and swallow its output. |
| # If its return code is non-zero, emit its output unless |always_silent| is |
| # True, and return the return code. |
| def RunCommand(command, always_silent=False): |
| try: |
| # Dart IO respects the following environment variables to configure the |
| # HttpClient proxy: https://api.dartlang.org/stable/1.22.1/dart-io/HttpClient/findProxyFromEnvironment.html |
| # We strip these to avoid problems with pub build and transformers. |
| no_http_proxy_env = os.environ.copy() |
| no_http_proxy_env.pop('http_proxy', None) |
| no_http_proxy_env.pop('HTTP_PROXY', None) |
| no_http_proxy_env.pop('https_proxy', None) |
| no_http_proxy_env.pop('HTTPS_PROXY', None) |
| subprocess.check_output(command, |
| stderr=subprocess.STDOUT, |
| env=no_http_proxy_env) |
| return 0 |
| except subprocess.CalledProcessError as e: |
| if not always_silent: |
| print ("Command failed: " + ' '.join(command) + "\n" + |
| "output: " + e.output) |
| DisplayFailureMessage() |
| return e.returncode |
| |
| def CreateTimestampFile(options): |
| if options.stamp != '': |
| dir_name = os.path.dirname(options.stamp) |
| if dir_name != '': |
| if not os.path.exists(dir_name): |
| os.mkdir(dir_name) |
| open(options.stamp, 'w').close() |
| |
| def BuildArguments(): |
| result = argparse.ArgumentParser(usage=usage) |
| result.add_argument("--dart-executable", help="dart executable", default=None) |
| result.add_argument("--pub-executable", help="pub executable", default=None) |
| result.add_argument("--directory", help="observatory root", default=None) |
| result.add_argument("--command", help="[get, build, deploy]", default=None) |
| result.add_argument("--silent", help="silence all output", default=None) |
| result.add_argument("--sdk", help="Use prebuilt sdk", default=None) |
| result.add_argument("--stamp", help="Write a stamp file", default='') |
| return result |
| |
| def ProcessOptions(options, args): |
| # Fix broken boolean parsing in argparse, where False ends up being True. |
| if (options.silent is not None) and (options.silent == "True"): |
| options.silent = True |
| elif (options.silent is None) or (options.silent == "False"): |
| options.silent = False |
| else: |
| print "--silent expects 'True' or 'False' argument." |
| return False |
| |
| if (options.sdk is not None) and (options.sdk == "True"): |
| options.sdk = True |
| elif (options.sdk is None) or (options.sdk == "False"): |
| options.sdk = False |
| else: |
| print "--sdk expects 'True' or 'False' argument." |
| return False |
| |
| # Required options. |
| if options.command is None or options.directory is None: |
| return False |
| |
| # Set a default value for pub_snapshot. |
| options.pub_snapshot = None |
| |
| # If we have a working pub executable, try and use that. |
| # TODO(whesse): Drop the pub-executable option if it isn't used. |
| if options.pub_executable is not None: |
| try: |
| if 0 == RunCommand([options.pub_executable, '--version'], |
| always_silent=True): |
| return True |
| except OSError as e: |
| pass |
| options.pub_executable = None |
| |
| if options.sdk and utils.CheckedInSdkCheckExecutable(): |
| # Use the checked in pub executable. |
| options.pub_snapshot = os.path.join(utils.CheckedInSdkPath(), |
| 'bin', |
| 'snapshots', |
| 'pub.dart.snapshot'); |
| try: |
| if 0 == RunCommand([utils.CheckedInSdkExecutable(), |
| options.pub_snapshot, |
| '--version'], always_silent=True): |
| return True |
| except OSError as e: |
| pass |
| options.pub_snapshot = None |
| |
| # We need a dart executable. |
| return (options.dart_executable is not None) |
| |
| def ChangeDirectory(directory): |
| os.chdir(directory); |
| |
| def PubCommand(dart_executable, |
| pub_executable, |
| pub_snapshot, |
| command, |
| silent): |
| if pub_executable is not None: |
| executable = [pub_executable] |
| elif pub_snapshot is not None: |
| executable = [utils.CheckedInSdkExecutable(), pub_snapshot] |
| else: |
| if not silent: |
| DisplayBootstrapWarning() |
| executable = [dart_executable, PUB_PATH] |
| # Prevent the bootstrap Dart executable from running in regular |
| # development flow. |
| # REMOVE THE FOLLOWING LINE TO USE the dart_bootstrap binary. |
| # return False |
| if not silent: |
| print >> sys.stderr, ('Running command "%s"') % (executable + command) |
| return RunCommand(executable + command) |
| |
| def Deploy(input_dir, output_dir): |
| shutil.rmtree(output_dir) |
| shutil.copytree(input_dir, output_dir, ignore=IGNORE_PATTERNS) |
| index_file = os.path.join(output_dir, 'web', 'index.html') |
| os.utime(index_file, None) |
| return 0 |
| |
| def RewritePubSpec(input_path, output_path, search, replace): |
| with open(input_path, 'rb') as input_file: |
| input_data = input_file.read() |
| input_data = input_data.replace(search, replace) |
| with open(output_path, 'wb+') as output_file: |
| output_file.write(input_data) |
| |
| def ExecuteCommand(options, args): |
| cmd = options.command |
| if (cmd == 'get'): |
| # Always remove pubspec.lock before running 'pub get'. |
| try: |
| os.remove('pubspec.lock'); |
| except OSError as e: |
| pass |
| return PubCommand(options.dart_executable, |
| options.pub_executable, |
| options.pub_snapshot, |
| ['get', '--offline'], |
| options.silent) |
| elif (cmd == 'build'): |
| return PubCommand(options.dart_executable, |
| options.pub_executable, |
| options.pub_snapshot, |
| ['build', |
| '-DOBS_VER=' + utils.GetVersion(ignore_svn_revision=True), |
| '--output', args[0]], |
| options.silent) |
| elif (cmd == 'deploy'): |
| Deploy('build', 'deployed') |
| elif (cmd == 'rewrite'): |
| RewritePubSpec(args[0], args[1], args[2], args[3]) |
| else: |
| print >> sys.stderr, ('ERROR: command "%s" not supported') % (cmd) |
| return -1; |
| |
| def main(): |
| # Sanity check that localhost can be resolved. |
| try: |
| socket.gethostbyname('localhost') |
| except: |
| print("The hostname 'localhost' could not be resolved. Please fix your" |
| "/etc/hosts file and try again") |
| return -1 |
| # Parse the options. |
| parser = BuildArguments() |
| (options, args) = parser.parse_known_args() |
| if not ProcessOptions(options, args): |
| parser.print_help() |
| return 1 |
| # Calculate absolute paths before changing directory. |
| if (options.dart_executable != None): |
| options.dart_executable = os.path.abspath(options.dart_executable) |
| if (options.pub_executable != None): |
| options.pub_executable = os.path.abspath(options.pub_executable) |
| if (options.pub_snapshot != None): |
| options.pub_snapshot = os.path.abspath(options.pub_snapshot) |
| if (options.stamp != ''): |
| options.stamp = os.path.abspath(options.stamp) |
| if len(args) == 1: |
| args[0] = os.path.abspath(args[0]) |
| try: |
| # Pub must be run from the project's root directory. |
| ChangeDirectory(options.directory) |
| result = ExecuteCommand(options, args) |
| if result == 0: |
| CreateTimestampFile(options) |
| return result |
| except: |
| DisplayFailureMessage() |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()); |