Commit 542da8cc authored by James Robinson's avatar James Robinson

Adds a run_mojo command that downloads sky_viewer.mojo and runs an flx in it

This initial version assumes the developer has mojo_shell and all other services
sitting on disk somewhere and that they're on linux and only want to run on
linux. This can be generalized down the line to support more use cases. This
downloads the sky_viewer.mojo corresponding to the packages/sky_engine/REVISION
in the developer's directory, so they can specify whatever revision they want.
sky_tools run_mojo downloads sky_viewer.mojo into its cache directory if it is
not present and constructs a command line to pass to mojo_shell that maps the
shebang stamped into the flx to the downloaded sky_viewer.mojo.

Since sky_viewer.mojo lives in the cloud and mojo_shell can load from the cloud
this could also map to an https URL. This should likely be an option.
parent 88a5cf95
......@@ -10,6 +10,7 @@ import 'package:sky_tools/src/build.dart';
import 'package:sky_tools/src/common.dart';
import 'package:sky_tools/src/init.dart';
import 'package:sky_tools/src/install.dart';
import 'package:sky_tools/src/run_mojo.dart';
void main(List<String> args) {
Logger.root.level = Level.WARNING;
......@@ -43,6 +44,7 @@ void main(List<String> args) {
new BuildCommandHandler(),
new InitCommandHandler(),
new InstallCommandHandler(),
new RunMojoCommandHandler(),
]) {
parser.addCommand(handler.name, handler.parser);
handlers[handler.name] = handler;
......
......@@ -11,13 +11,16 @@ import 'package:logging/logging.dart';
final Logger _logging = new Logger('sky_tools.device');
enum Artifact {
FlutterCompiler,
}
enum Artifact { FlutterCompiler, SkyViewerMojo, }
class _ArtifactStore {
_ArtifactStore._();
// Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/big_red_button.py#L50
String _googleStorageUrl(String category, String name, String engineRevision) {
return 'https://storage.googleapis.com/mojo/sky/${category}/linux-x64/${engineRevision}/${name}';
}
Future _downloadFile(String url, File file) async {
_logging.fine('Downloading $url to ${file.path}');
HttpClient httpClient = new HttpClient();
......@@ -44,23 +47,39 @@ class _ArtifactStore {
return cacheDir;
}
// Whether the artifact needs to be marked as executable on disk.
bool _needsToBeExecutable(Artifact artifact) {
return artifact == Artifact.FlutterCompiler;
}
Future<String> getPath(Artifact artifact, String packageRoot) async {
String engineRevision = await _getEngineRevision(packageRoot);
Directory cacheDir = await _cacheDir(engineRevision, packageRoot);
String category, name;
if (artifact == Artifact.FlutterCompiler) {
File skySnapshotFile = new File(cacheDir.path + 'sky_snapshot');
if (!await skySnapshotFile.exists()) {
_logging.info('Downloading sky_snapshot from the cloud, one moment please...');
String googleStorageUrl = 'https://storage.googleapis.com/mojo/sky/shell/linux-x64/${engineRevision}/sky_snapshot';
await _downloadFile(googleStorageUrl, skySnapshotFile);
ProcessResult result = await Process.run('chmod', ['u+x', skySnapshotFile.path]);
category = 'shell';
name = 'sky_snapshot';
} else if (artifact == Artifact.SkyViewerMojo) {
category = 'viewer';
name = 'sky_viewer.mojo';
} else {
// Unknown artifact.
return '';
}
File cachedFile = new File(cacheDir.path + name);
if (!await cachedFile.exists()) {
_logging.info('Downloading ${name} from the cloud, one moment please...');
String googleStorageUrl = _googleStorageUrl(category, name, engineRevision);
await _downloadFile(googleStorageUrl, cachedFile);
if (_needsToBeExecutable(artifact)) {
ProcessResult result = await Process.run('chmod', ['u+x', cachedFile.path]);
if (result.exitCode != 0) throw new Exception(result.stderr);
}
return skySnapshotFile.path;
}
return '';
return cachedFile.path;
}
}
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library sky_tools.run_mojo;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'artifacts.dart';
import 'common.dart';
final Logger _logging = new Logger('sky_tools.run_mojo');
class RunMojoCommandHandler extends CommandHandler {
RunMojoCommandHandler() : super('run_mojo', 'Run a Flutter app in mojo.');
ArgParser get parser {
ArgParser parser = new ArgParser();
parser.addFlag('help', abbr: 'h', negatable: false);
parser.addOption('package-root', defaultsTo: 'packages');
parser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services');
parser.addOption('app', defaultsTo: 'app.flx');
return parser;
}
Future<String> _makePathAbsolute(String relativePath) async {
File file = new File(relativePath);
if (!await file.exists()) {
throw new Exception("Path \"${relativePath}\" does not exist");
}
return file.absolute.path;
}
@override
Future<int> processArgResults(ArgResults results) async {
if (results['help']) {
print(parser.usage);
return 0;
}
if (results['mojo-path'] == null) {
_logging.severe('Must specify --mojo-path to mojo_run');
return 1;
}
String packageRoot = results['package-root'];
String appPath = await _makePathAbsolute(results['app']);
String viewerPath = await _makePathAbsolute(await artifactStore.getPath(Artifact.SkyViewerMojo, packageRoot));
String mojoShellPath = await _makePathAbsolute(path.join(results['mojo-path'], 'mojo_shell'));
List<String> mojoRunArgs = [
'mojo:window_manager file://${appPath}',
'--url-mappings=mojo:window_manager=mojo:kiosk_wm,mojo:sky_viewer=file://${viewerPath}'
];
_logging.fine("Starting ${mojoShellPath} with args: ${mojoRunArgs}");
Process proc = await Process.start(mojoShellPath, mojoRunArgs);
proc.stdout.transform(UTF8.decoder).listen((data) {
stdout.write(data);
});
proc.stderr.transform(UTF8.decoder).listen((data) {
stderr.write(data);
});
int exitCode = await proc.exitCode;
if (exitCode != 0) throw new Exception(exitCode);
return 0;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment