Chromium Code Reviews| Index: sky/sdk/tools/sky |
| diff --git a/sky/tools/shelldb b/sky/sdk/tools/sky |
| similarity index 59% |
| copy from sky/tools/shelldb |
| copy to sky/sdk/tools/sky |
| index 2311f58f55fe06b0620a71e06955f8918786a4dc..4c17cc01ab1622cfb7159859d9ce9ef1faf1a769 100755 |
| --- a/sky/tools/shelldb |
| +++ b/sky/sdk/tools/sky |
| @@ -3,25 +3,25 @@ |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| -from skypy.skyserver import SkyServer |
| import argparse |
| import json |
| import logging |
| import os |
| +import signal |
| +import socket |
| import subprocess |
| import sys |
| import urlparse |
| -SKY_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__)) |
| -SKY_ROOT = os.path.dirname(SKY_TOOLS_DIR) |
| -SRC_ROOT = os.path.dirname(SKY_ROOT) |
| +SDK_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__)) |
| +SDK_ROOT = os.path.dirname(SDK_TOOLS_DIR) |
| SKY_SERVER_PORT = 9888 |
| -DEFAULT_URL = "sky://domokit.github.io/home" |
| +DEFAULT_URL = os.path.join(SDK_ROOT, "examples/index.sky") |
| APK_NAME = 'SkyDemo.apk' |
| -ADB_PATH = os.path.join(SRC_ROOT, |
| - 'third_party/android_tools/sdk/platform-tools/adb') |
| - |
| +ANDROID_PACKAGE = "org.domokit.sky.demo" |
| +# FIXME: This assumes adb is in $PATH, we could look for ANDROID_HOME, etc? |
| +ADB_PATH = 'adb' |
| PID_FILE_PATH = "/tmp/skydemo.pids" |
| PID_FILE_KEYS = frozenset([ |
| @@ -32,6 +32,20 @@ PID_FILE_KEYS = frozenset([ |
| 'build_dir', |
| ]) |
| + |
| +def _port_in_use(port): |
| + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| + return sock.connect_ex(('localhost', port)) == 0 |
| + |
| + |
| +# We need something to serve sky files, python's httpserver is sufficient. |
| +def _start_http_server(port, root): |
| + server_command = [ |
| + 'python', '-m', 'SimpleHTTPServer', str(port), |
| + ] |
| + return subprocess.Popen(server_command, cwd=root).pid |
| + |
| + |
| # This 'strict dictionary' approach is useful for catching typos. |
| class Pids(object): |
| def __init__(self, known_keys, contents=None): |
| @@ -67,6 +81,10 @@ class Pids(object): |
| def clear(self): |
| self._dict = {} |
| + def pop(self, key, default=None): |
| + assert key in self._known_keys, '%s not in known_keys' % key |
| + return self._dict.pop(key, default) |
| + |
| @classmethod |
| def read_from(cls, path, known_keys): |
| contents = {} |
| @@ -86,77 +104,69 @@ class Pids(object): |
| logging.warn('Failed to write pid file: %s' % path) |
| -def _convert_to_sky_url(url): |
| - parts = urlparse.urlsplit(url) |
| - parts = parts._replace(scheme='sky') |
| - return parts.geturl() |
| - |
| - |
| -# A free function for possible future sharing with a 'load' command. |
| -def _url_from_args(args, pids): |
| - if urlparse.urlparse(args.url_or_path).scheme: |
| - return args.url_or_path |
| - # The load happens on the remote device, use the remote port. |
| - remote_sky_server_port = pids.get('remote_sky_server_port', |
| - pids['sky_server_port']) |
| - url = SkyServer.url_for_path(remote_sky_server_port, |
| - pids['sky_server_root'], args.url_or_path) |
| - return _convert_to_sky_url(url) |
| +def _url_for_path(port, root, path): |
| + relative_path = os.path.relpath(path, root) |
| + return 'sky://localhost:%s/%s' % (port, relative_path) |
| class StartSky(object): |
| def add_subparser(self, subparsers): |
| start_parser = subparsers.add_parser('start', |
| help='launch SKyShell.apk on the device') |
| - start_parser.add_argument('build_dir', type=str) |
| - start_parser.add_argument('url_or_path', nargs='?', type=str, |
| - default=DEFAULT_URL) |
| + start_parser.add_argument('--install', action='store_true') |
| + start_parser.add_argument('project_or_path', nargs='?', type=str, |
| + default='main.sky') |
| start_parser.set_defaults(func=self.run) |
| - def _server_root_for_url(self, url_or_path): |
| - path = os.path.abspath(url_or_path) |
| - if os.path.commonprefix([path, SRC_ROOT]) == SRC_ROOT: |
| - server_root = SRC_ROOT |
| - else: |
| - server_root = os.path.dirname(path) |
| - logging.warn( |
| - '%s is outside of mojo root, using %s as server root' % |
| - (path, server_root)) |
| - return server_root |
| - |
| - def _sky_server_for_args(self, args): |
| - # FIXME: This is a hack. sky_server should just take a build_dir |
| - # not a magical "configuration" name. |
| - configuration = os.path.basename(os.path.normpath(args.build_dir)) |
| - server_root = self._server_root_for_url(args.url_or_path) |
| - sky_server = SkyServer(SKY_SERVER_PORT, configuration, server_root) |
| - return sky_server |
| - |
| def run(self, args, pids): |
| - apk_path = os.path.join(args.build_dir, 'apks', APK_NAME) |
| - if not os.path.exists(apk_path): |
| - print "'%s' does not exist?" % apk_path |
| - return 2 |
| + StopSky().run(args, pids) |
| + if args.install: |
| + apk_path = os.path.join(SDK_ROOT, 'apks', APK_NAME) |
| + if not os.path.exists(apk_path): |
| + print "'%s' does not exist?" % apk_path |
| + return 2 |
| + |
| + subprocess.check_call([ADB_PATH, 'install', '-r', apk_path]) |
| - sky_server = self._sky_server_for_args(args) |
| - pids['sky_server_pid'] = sky_server.start() |
| - pids['sky_server_port'] = sky_server.port |
| - pids['sky_server_root'] = sky_server.root |
| + project_or_path = os.path.abspath(args.project_or_path) |
| + |
| + if os.path.isdir(project_or_path): |
| + sky_server_root = project_or_path |
| + main_sky = os.path.join(project_or_path, 'main.sky') |
| + missing_msg = "Missing main.sky in project: %s" % sky_server_root |
| + else: |
| + sky_server_root = os.path.dirname(project_or_path) |
| + main_sky = project_or_path |
| + missing_msg = "%s does not exist." % main_sky |
| - pids['build_dir'] = os.path.abspath(args.build_dir) |
| + if not os.path.isfile(main_sky): |
| + print missing_msg |
| + return 2 |
| - subprocess.check_call([ADB_PATH, 'install', '-r', apk_path]) |
| + sky_server_port = SKY_SERVER_PORT |
| + pids['sky_server_port'] = sky_server_port |
| + if _port_in_use(sky_server_port): |
| + logging.warn(('Port %s already in use. ' |
| + ' Not starting server for %s') % (sky_server_port, sky_server_root)) |
| + else: |
| + sky_server_pid = _start_http_server(sky_server_port, sky_server_root) |
| + pids['sky_server_pid'] = sky_server_pid |
| + pids['sky_server_root'] = sky_server_root |
| - port_string = 'tcp:%s' % sky_server.port |
| + port_string = 'tcp:%s' % sky_server_port |
| subprocess.check_call([ |
| ADB_PATH, 'reverse', port_string, port_string |
| ]) |
| - pids['remote_sky_server_port'] = sky_server.port |
| + pids['remote_sky_server_port'] = sky_server_port |
| + |
| + # The load happens on the remote device, use the remote port. |
| + sky_url = _url_for_path(pids['remote_sky_server_port'], sky_server_root, |
| + main_sky) |
| subprocess.check_call([ADB_PATH, 'shell', |
| 'am', 'start', |
| '-a', 'android.intent.action.VIEW', |
| - '-d', _url_from_args(args, pids)]) |
| + '-d', sky_url]) |
| class StopSky(object): |
| @@ -179,8 +189,8 @@ class StopSky(object): |
| def run(self, args, pids): |
| self._kill_if_exists(pids, 'sky_server_pid', 'sky_server') |
| - if 'remote_sky_server_port' in self.pids: |
| - port_string = 'tcp:%s' % self.pids['remote_sky_server_port'] |
| + if 'remote_sky_server_port' in pids: |
| + port_string = 'tcp:%s' % pids['remote_sky_server_port'] |
| subprocess.call([ADB_PATH, 'reverse', '--remove', port_string]) |
| subprocess.call([ |
| @@ -189,6 +199,7 @@ class StopSky(object): |
| pids.clear() |
| +# TODO(eseidel): I'm not quite sure what to do about the bindings paths yet. |
| class Analyze(object): |
| def add_subparser(self, subparsers): |
| analyze_parser = subparsers.add_parser('analyze', |
| @@ -197,7 +208,13 @@ class Analyze(object): |
| analyze_parser.set_defaults(func=self.run) |
| def run(self, args, pids): |
| - ANALYZER_PATH = 'third_party/dart-sdk/dart-sdk/bin/dartanalyzer' |
| + DART_SDK_PATH = os.env.get('DART_SDK') |
| + if DART_SDK_PATH is None or not os.path.exists(DART_SDK_PATH): |
| + print ("Can't find dart-sdk at %s. " |
| + "Did you set DART_SDK in the environment?") % DART_SDK_PATH |
| + return 2 |
| + |
| + ANALYZER_PATH = os.path.join(DART_SDK_PATH, 'bin/dartanalyzer') |
| build_dir = os.path.abspath(pids['build_dir']) |
| bindings_path = os.path.join(build_dir, 'gen/sky/bindings') |
| @@ -210,8 +227,8 @@ class Analyze(object): |
| analyzer_args = [ANALYZER_PATH, |
| "--url-mapping=dart:sky,%s" % dart_sky_path, |
| "--url-mapping=dart:sky_builtin,%s" % sky_builtin_path, |
| - "--url-mapping=dart:mojo.bindings,%s" % mojo_bindings_path, |
| - "--url-mapping=dart:mojo.core,%s" % mojo_core_path, |
| + "--url-mapping=mojo:bindings,%s" % mojo_bindings_path, |
| + "--url-mapping=mojo:core,%s" % mojo_core_path, |
|
abarth-chromium
2015/03/13 20:38:02
Bad merge?
|
| args.app_path |
| ] |
| subprocess.call(analyzer_args) |
| @@ -221,10 +238,10 @@ class SkyShellRunner(object): |
| def main(self): |
| logging.basicConfig(level=logging.WARNING) |
| - parser = argparse.ArgumentParser(description='Sky Shell Runner') |
| + parser = argparse.ArgumentParser(description='Sky Demo Runner') |
| subparsers = parser.add_subparsers(help='sub-command help') |
| - for command in [StartSky(), StopSky(), Analyze()]: |
| + for command in [StartSky(), StopSky()]: |
|
abarth-chromium
2015/03/13 20:38:02
Remove code for analyzer?
|
| command.add_subparser(subparsers) |
| args = parser.parse_args() |