blob: 817e921777520f2ec0be602a8c0ed4392f49b824 [file] [log] [blame]
// Copyright (c) 2019, 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.
import 'dart:io';
import 'dart:typed_data' show Uint8List;
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'config.dart';
Logger _logger = Logger('flutter_web');
/// Handle provisioning package:flutter_web and related work.
class FlutterWebManager {
final String sdkPath;
Directory _projectDirectory;
bool _initedFlutterWeb = false;
FlutterWebManager(this.sdkPath) {
_projectDirectory = Directory.systemTemp.createTempSync('dartpad');
_init();
}
void dispose() {
_projectDirectory.deleteSync(recursive: true);
}
Directory get projectDirectory => _projectDirectory;
String get packagesFilePath => path.join(projectDirectory.path, '.packages');
void _init() {
// create a pubspec.yaml file
String pubspec = createPubspec(false);
File(path.join(_projectDirectory.path, 'pubspec.yaml'))
.writeAsStringSync(pubspec);
// create a .packages file
final String packagesFileContents = '''
$_samplePackageName:lib/
''';
File(path.join(_projectDirectory.path, '.packages'))
.writeAsStringSync(packagesFileContents);
// and create a lib/ folder for completeness
Directory(path.join(_projectDirectory.path, 'lib')).createSync();
}
Future<void> warmup() async {
try {
await initFlutterWeb();
} catch (e, s) {
_logger.warning('Error initializing flutter web', e, s);
}
}
Future<void> initFlutterWeb() async {
if (_initedFlutterWeb) {
return;
}
_logger.info('creating flutter web pubspec');
String pubspec = createPubspec(true);
File(path.join(_projectDirectory.path, 'pubspec.yaml'))
.writeAsStringSync(pubspec);
_runPubGet();
final String sdkVersion =
File('dart-sdk.version').readAsStringSync().trim();
// download and save the flutter_web.sum file
String url = 'https://storage.googleapis.com/compilation_artifacts/'
'$sdkVersion/flutter_web.sum';
Uint8List summaryContents = await http.readBytes(url);
File(path.join(_projectDirectory.path, 'flutter_web.sum'))
.writeAsBytesSync(summaryContents);
_initedFlutterWeb = true;
}
String get summaryFilePath {
return path.join(_projectDirectory.path, 'flutter_web.sum');
}
static final Set<String> _flutterWebImportPrefixes = <String>{
'package:flutter_web',
'package:flutter_web_ui',
'package:flutter_web_test',
};
bool usesFlutterWeb(Set<String> imports) {
return imports.any((String import) {
return _flutterWebImportPrefixes.any(
(String prefix) => import.startsWith(prefix),
);
});
}
bool hasUnsupportedImport(Set<String> imports) {
return getUnsupportedImport(imports) != null;
}
String getUnsupportedImport(Set<String> imports) {
// TODO(devoncarew): Should we support a white-listed set of package:
// imports?
for (String import in imports) {
// All dart: imports are ok;
if (import.startsWith('dart:')) {
continue;
}
// Currently we only allow flutter web imports.
if (import.startsWith('package:')) {
if (_flutterWebImportPrefixes
.any((String prefix) => import.startsWith(prefix))) {
continue;
}
return import;
}
// Don't allow file imports.
return import;
}
return null;
}
void _runPubGet() {
_logger.info('running pub get (${_projectDirectory.path})');
ProcessResult result = Process.runSync(
path.join(sdkPath, 'bin', 'pub'),
<String>['get', '--no-precompile'],
workingDirectory: _projectDirectory.path,
);
_logger.info('${result.stdout}'.trim());
if (result.exitCode != 0) {
_logger.warning('pub get failed: ${result.exitCode}');
_logger.warning(result.stderr);
throw 'pub get failed: ${result.exitCode}';
}
}
static const String _samplePackageName = 'dartpad_sample';
static String createPubspec(bool includeFlutterWeb) {
final Config config = Config.getConfig();
// In order to provision package:flutter_web for a local checkout, create a
// file named 'config.properties' in the dart-services repo root.
// Add an entry, 'flutter_repo_path=<path/to/flutter_web/repo>', which
// points to a local checkout of the flutter_web repository.
String flutter_repo_path = config.getValue('flutter_repo_path');
String content = '''
name: $_samplePackageName
''';
if (includeFlutterWeb) {
content += '''
dependencies:
flutter_web:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web
flutter_web_test:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web_test
flutter_web_ui:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web_ui
''';
if (flutter_repo_path != null) {
content += '''
dependency_overrides:
flutter_web:
path: $flutter_repo_path/packages/flutter_web
flutter_web_test:
path: $flutter_repo_path/packages/flutter_web_test
flutter_web_ui:
path: $flutter_repo_path/packages/flutter_web_ui
''';
}
}
return content;
}
}