mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
This reverts commit 0349660622
.
This commit is contained in:
parent
03a59bff03
commit
ef62092b9b
@ -191,7 +191,7 @@ FileSystem crashFileSystem = const LocalFileSystem();
|
||||
|
||||
/// Saves the crash report to a local file.
|
||||
Future<File> _createLocalCrashReport(List<String> args, dynamic error, StackTrace stackTrace, String doctorText) async {
|
||||
File crashFile = fsUtils.getUniqueFile(crashFileSystem.currentDirectory, 'flutter', 'log');
|
||||
File crashFile = getUniqueFile(crashFileSystem.currentDirectory, 'flutter', 'log');
|
||||
|
||||
final StringBuffer buffer = StringBuffer();
|
||||
|
||||
@ -211,7 +211,7 @@ Future<File> _createLocalCrashReport(List<String> args, dynamic error, StackTrac
|
||||
crashFile.writeAsStringSync(buffer.toString());
|
||||
} on FileSystemException catch (_) {
|
||||
// Fallback to the system temporary directory.
|
||||
crashFile = fsUtils.getUniqueFile(crashFileSystem.systemTempDirectory, 'flutter', 'log');
|
||||
crashFile = getUniqueFile(crashFileSystem.systemTempDirectory, 'flutter', 'log');
|
||||
try {
|
||||
crashFile.writeAsStringSync(buffer.toString());
|
||||
} on FileSystemException catch (e) {
|
||||
|
@ -98,7 +98,7 @@ class GradleUtils {
|
||||
|
||||
/// Injects the Gradle wrapper files if any of these files don't exist in [directory].
|
||||
void injectGradleWrapperIfNeeded(Directory directory) {
|
||||
fsUtils.copyDirectorySync(
|
||||
copyDirectorySync(
|
||||
globals.cache.getArtifactDirectory('gradle_wrapper'),
|
||||
directory,
|
||||
shouldCopyFile: (File sourceFile, File destinationFile) {
|
||||
@ -267,10 +267,10 @@ void updateLocalProperties({
|
||||
}
|
||||
|
||||
if (androidSdk != null) {
|
||||
changeIfNecessary('sdk.dir', fsUtils.escapePath(androidSdk.directory));
|
||||
changeIfNecessary('sdk.dir', escapePath(androidSdk.directory));
|
||||
}
|
||||
|
||||
changeIfNecessary('flutter.sdk', fsUtils.escapePath(Cache.flutterRoot));
|
||||
changeIfNecessary('flutter.sdk', escapePath(Cache.flutterRoot));
|
||||
if (buildInfo != null) {
|
||||
changeIfNecessary('flutter.buildMode', buildInfo.modeName);
|
||||
final String buildName = validatedBuildNameForPlatform(
|
||||
@ -296,7 +296,7 @@ void updateLocalProperties({
|
||||
void writeLocalProperties(File properties) {
|
||||
final SettingsFile settings = SettingsFile();
|
||||
if (androidSdk != null) {
|
||||
settings.values['sdk.dir'] = fsUtils.escapePath(androidSdk.directory);
|
||||
settings.values['sdk.dir'] = escapePath(androidSdk.directory);
|
||||
}
|
||||
settings.writeContents(properties);
|
||||
}
|
||||
|
@ -11,10 +11,7 @@ import 'utils.dart';
|
||||
class Config {
|
||||
Config([File configFile, Logger localLogger]) {
|
||||
final Logger loggerInstance = localLogger ?? globals.logger;
|
||||
_configFile = configFile ?? globals.fs.file(globals.fs.path.join(
|
||||
fsUtils.userHomePath,
|
||||
'.flutter_settings',
|
||||
));
|
||||
_configFile = configFile ?? globals.fs.file(globals.fs.path.join(userHomePath(), '.flutter_settings'));
|
||||
if (_configFile.existsSync()) {
|
||||
try {
|
||||
_values = castStringKeyedMap(json.decode(_configFile.readAsStringSync()));
|
||||
|
@ -4,15 +4,94 @@
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import '../globals.dart' as globals;
|
||||
import 'common.dart' show throwToolExit;
|
||||
import 'context.dart';
|
||||
|
||||
export 'package:file/file.dart';
|
||||
export 'package:file/local.dart';
|
||||
|
||||
/// Create the ancestor directories of a file path if they do not already exist.
|
||||
void ensureDirectoryExists(String filePath) {
|
||||
final String dirPath = globals.fs.path.dirname(filePath);
|
||||
if (globals.fs.isDirectorySync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
globals.fs.directory(dirPath).createSync(recursive: true);
|
||||
} on FileSystemException catch (e) {
|
||||
throwToolExit('Failed to create directory "$dirPath": ${e.osError.message}');
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates `destDir` if needed, then recursively copies `srcDir` to `destDir`,
|
||||
/// invoking [onFileCopied], if specified, for each source/destination file pair.
|
||||
///
|
||||
/// Skips files if [shouldCopyFile] returns `false`.
|
||||
void copyDirectorySync(
|
||||
Directory srcDir,
|
||||
Directory destDir, {
|
||||
bool shouldCopyFile(File srcFile, File destFile),
|
||||
void onFileCopied(File srcFile, File destFile),
|
||||
}) {
|
||||
if (!srcDir.existsSync()) {
|
||||
throw Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
|
||||
}
|
||||
|
||||
if (!destDir.existsSync()) {
|
||||
destDir.createSync(recursive: true);
|
||||
}
|
||||
|
||||
for (final FileSystemEntity entity in srcDir.listSync()) {
|
||||
final String newPath = destDir.fileSystem.path.join(destDir.path, entity.basename);
|
||||
if (entity is File) {
|
||||
final File newFile = destDir.fileSystem.file(newPath);
|
||||
if (shouldCopyFile != null && !shouldCopyFile(entity, newFile)) {
|
||||
continue;
|
||||
}
|
||||
newFile.writeAsBytesSync(entity.readAsBytesSync());
|
||||
onFileCopied?.call(entity, newFile);
|
||||
} else if (entity is Directory) {
|
||||
copyDirectorySync(
|
||||
entity,
|
||||
destDir.fileSystem.directory(newPath),
|
||||
shouldCopyFile: shouldCopyFile,
|
||||
onFileCopied: onFileCopied,
|
||||
);
|
||||
} else {
|
||||
throw Exception('${entity.path} is neither File nor Directory');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Canonicalizes [path].
|
||||
///
|
||||
/// This function implements the behavior of `canonicalize` from
|
||||
/// `package:path`. However, unlike the original, it does not change the ASCII
|
||||
/// case of the path. Changing the case can break hot reload in some situations,
|
||||
/// for an example see: https://github.com/flutter/flutter/issues/9539.
|
||||
String canonicalizePath(String path) => globals.fs.path.normalize(globals.fs.path.absolute(path));
|
||||
|
||||
/// Escapes [path].
|
||||
///
|
||||
/// On Windows it replaces all '\' with '\\'. On other platforms, it returns the
|
||||
/// path unchanged.
|
||||
String escapePath(String path) => globals.platform.isWindows ? path.replaceAll('\\', '\\\\') : path;
|
||||
|
||||
/// Returns true if the file system [entity] has not been modified since the
|
||||
/// latest modification to [referenceFile].
|
||||
///
|
||||
/// Returns true, if [entity] does not exist.
|
||||
///
|
||||
/// Returns false, if [entity] exists, but [referenceFile] does not.
|
||||
bool isOlderThanReference({ @required FileSystemEntity entity, @required File referenceFile }) {
|
||||
if (!entity.existsSync()) {
|
||||
return true;
|
||||
}
|
||||
return referenceFile.existsSync()
|
||||
&& referenceFile.statSync().modified.isAfter(entity.statSync().modified);
|
||||
}
|
||||
|
||||
/// Exception indicating that a file that was expected to exist was not found.
|
||||
class FileNotFoundException implements IOException {
|
||||
const FileNotFoundException(this.path);
|
||||
@ -23,130 +102,10 @@ class FileNotFoundException implements IOException {
|
||||
String toString() => 'File not found: $path';
|
||||
}
|
||||
|
||||
final FileSystemUtils _defaultFileSystemUtils = FileSystemUtils(
|
||||
fileSystem: globals.fs,
|
||||
platform: globals.platform,
|
||||
);
|
||||
|
||||
FileSystemUtils get fsUtils => context.get<FileSystemUtils>() ?? _defaultFileSystemUtils;
|
||||
|
||||
/// Various convenience file system methods.
|
||||
class FileSystemUtils {
|
||||
FileSystemUtils({
|
||||
@required FileSystem fileSystem,
|
||||
@required Platform platform,
|
||||
}) : _fileSystem = fileSystem,
|
||||
_platform = platform;
|
||||
|
||||
final FileSystem _fileSystem;
|
||||
|
||||
final Platform _platform;
|
||||
|
||||
/// Create the ancestor directories of a file path if they do not already exist.
|
||||
void ensureDirectoryExists(String filePath) {
|
||||
final String dirPath = _fileSystem.path.dirname(filePath);
|
||||
if (_fileSystem.isDirectorySync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_fileSystem.directory(dirPath).createSync(recursive: true);
|
||||
} on FileSystemException catch (e) {
|
||||
throwToolExit('Failed to create directory "$dirPath": ${e.osError.message}');
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates `destDir` if needed, then recursively copies `srcDir` to
|
||||
/// `destDir`, invoking [onFileCopied], if specified, for each
|
||||
/// source/destination file pair.
|
||||
///
|
||||
/// Skips files if [shouldCopyFile] returns `false`.
|
||||
void copyDirectorySync(
|
||||
Directory srcDir,
|
||||
Directory destDir, {
|
||||
bool shouldCopyFile(File srcFile, File destFile),
|
||||
void onFileCopied(File srcFile, File destFile),
|
||||
}) {
|
||||
if (!srcDir.existsSync()) {
|
||||
throw Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
|
||||
}
|
||||
|
||||
if (!destDir.existsSync()) {
|
||||
destDir.createSync(recursive: true);
|
||||
}
|
||||
|
||||
for (final FileSystemEntity entity in srcDir.listSync()) {
|
||||
final String newPath = destDir.fileSystem.path.join(destDir.path, entity.basename);
|
||||
if (entity is File) {
|
||||
final File newFile = destDir.fileSystem.file(newPath);
|
||||
if (shouldCopyFile != null && !shouldCopyFile(entity, newFile)) {
|
||||
continue;
|
||||
}
|
||||
newFile.writeAsBytesSync(entity.readAsBytesSync());
|
||||
onFileCopied?.call(entity, newFile);
|
||||
} else if (entity is Directory) {
|
||||
copyDirectorySync(
|
||||
entity,
|
||||
destDir.fileSystem.directory(newPath),
|
||||
shouldCopyFile: shouldCopyFile,
|
||||
onFileCopied: onFileCopied,
|
||||
);
|
||||
} else {
|
||||
throw Exception('${entity.path} is neither File nor Directory');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends a number to a filename in order to make it unique under a
|
||||
/// directory.
|
||||
File getUniqueFile(Directory dir, String baseName, String ext) {
|
||||
final FileSystem fs = dir.fileSystem;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
final String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
|
||||
final File file = fs.file(_fileSystem.path.join(dir.path, name));
|
||||
if (!file.existsSync()) {
|
||||
return file;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a relative path if [fullPath] is contained by the cwd, else return an
|
||||
/// absolute path.
|
||||
String getDisplayPath(String fullPath) {
|
||||
final String cwd = _fileSystem.currentDirectory.path + _fileSystem.path.separator;
|
||||
return fullPath.startsWith(cwd) ? fullPath.substring(cwd.length) : fullPath;
|
||||
}
|
||||
|
||||
/// Escapes [path].
|
||||
///
|
||||
/// On Windows it replaces all '\' with '\\'. On other platforms, it returns the
|
||||
/// path unchanged.
|
||||
String escapePath(String path) => _platform.isWindows ? path.replaceAll('\\', '\\\\') : path;
|
||||
|
||||
/// Returns true if the file system [entity] has not been modified since the
|
||||
/// latest modification to [referenceFile].
|
||||
///
|
||||
/// Returns true, if [entity] does not exist.
|
||||
///
|
||||
/// Returns false, if [entity] exists, but [referenceFile] does not.
|
||||
bool isOlderThanReference({
|
||||
@required FileSystemEntity entity,
|
||||
@required File referenceFile,
|
||||
}) {
|
||||
if (!entity.existsSync()) {
|
||||
return true;
|
||||
}
|
||||
return referenceFile.existsSync()
|
||||
&& referenceFile.statSync().modified.isAfter(entity.statSync().modified);
|
||||
}
|
||||
|
||||
/// Reads the process environment to find the current user's home directory.
|
||||
///
|
||||
/// If the searched environment variables are not set, '.' is returned instead.
|
||||
String get userHomePath {
|
||||
final String envKey = _platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
|
||||
return _platform.environment[envKey] ?? '.';
|
||||
}
|
||||
/// Reads the process environment to find the current user's home directory.
|
||||
///
|
||||
/// If the searched environment variables are not set, '.' is returned instead.
|
||||
String userHomePath() {
|
||||
final String envKey = globals.platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME';
|
||||
return globals.platform.environment[envKey] ?? '.';
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import 'dart:io' as io
|
||||
InternetAddressType,
|
||||
IOSink,
|
||||
NetworkInterface,
|
||||
pid,
|
||||
Process,
|
||||
ProcessInfo,
|
||||
ProcessSignal,
|
||||
@ -253,14 +252,6 @@ Stream<List<int>> get stdin => globals.stdio.stdin;
|
||||
io.IOSink get stderr => globals.stdio.stderr;
|
||||
bool get stdinHasTerminal => globals.stdio.stdinHasTerminal;
|
||||
|
||||
// TODO(zra): Move pid and writePidFile into `ProcessInfo`.
|
||||
void writePidFile(String pidFile) {
|
||||
if (pidFile != null) {
|
||||
// Write our pid to the file.
|
||||
globals.fs.file(pidFile).writeAsStringSync(io.pid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/// An overridable version of io.ProcessInfo.
|
||||
abstract class ProcessInfo {
|
||||
factory ProcessInfo() => _DefaultProcessInfo();
|
||||
|
@ -11,6 +11,7 @@ import 'package:meta/meta.dart';
|
||||
import '../convert.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import 'file_system.dart';
|
||||
import 'io.dart' as io;
|
||||
import 'terminal.dart';
|
||||
|
||||
/// Convert `foo_bar` to `fooBar`.
|
||||
@ -50,10 +51,29 @@ String getEnumName(dynamic enumItem) {
|
||||
return index == -1 ? name : name.substring(index + 1);
|
||||
}
|
||||
|
||||
File getUniqueFile(Directory dir, String baseName, String ext) {
|
||||
final FileSystem fs = dir.fileSystem;
|
||||
int i = 1;
|
||||
|
||||
while (true) {
|
||||
final String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
|
||||
final File file = fs.file(globals.fs.path.join(dir.path, name));
|
||||
if (!file.existsSync()) {
|
||||
return file;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
String toPrettyJson(Object jsonable) {
|
||||
return const JsonEncoder.withIndent(' ').convert(jsonable) + '\n';
|
||||
}
|
||||
|
||||
/// Return a String - with units - for the size in MB of the given number of bytes.
|
||||
String getSizeAsMB(int bytesLength) {
|
||||
return '${(bytesLength / (1024 * 1024)).toStringAsFixed(1)}MB';
|
||||
}
|
||||
|
||||
final NumberFormat kSecondsFormat = NumberFormat('0.0');
|
||||
final NumberFormat kMillisecondsFormat = NumberFormat.decimalPattern();
|
||||
|
||||
@ -66,9 +86,11 @@ String getElapsedAsMilliseconds(Duration duration) {
|
||||
return '${kMillisecondsFormat.format(duration.inMilliseconds)}ms';
|
||||
}
|
||||
|
||||
/// Return a String - with units - for the size in MB of the given number of bytes.
|
||||
String getSizeAsMB(int bytesLength) {
|
||||
return '${(bytesLength / (1024 * 1024)).toStringAsFixed(1)}MB';
|
||||
/// Return a relative path if [fullPath] is contained by the cwd, else return an
|
||||
/// absolute path.
|
||||
String getDisplayPath(String fullPath) {
|
||||
final String cwd = globals.fs.currentDirectory.path + globals.fs.path.separator;
|
||||
return fullPath.startsWith(cwd) ? fullPath.substring(cwd.length) : fullPath;
|
||||
}
|
||||
|
||||
/// A class to maintain a list of items, fire events when items are added or
|
||||
@ -293,6 +315,13 @@ String wrapText(String text, { int columnWidth, int hangingIndent, int indent, b
|
||||
return result.join('\n');
|
||||
}
|
||||
|
||||
void writePidFile(String pidFile) {
|
||||
if (pidFile != null) {
|
||||
// Write our pid to the file.
|
||||
globals.fs.file(pidFile).writeAsStringSync(io.pid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Used to represent a run of ANSI control sequences next to a visible
|
||||
// character.
|
||||
class _AnsiRun {
|
||||
|
@ -14,7 +14,6 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
|
||||
import '../application_package.dart';
|
||||
import '../base/async_guard.dart';
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/net.dart';
|
||||
@ -389,10 +388,7 @@ class _ExperimentalResidentWebRunner extends ResidentWebRunner {
|
||||
return 1;
|
||||
}
|
||||
final String modeName = debuggingOptions.buildInfo.friendlyModeName;
|
||||
globals.printStatus(
|
||||
'Launching ${fsUtils.getDisplayPath(target)} '
|
||||
'on ${device.device.name} in $modeName mode...',
|
||||
);
|
||||
globals.printStatus('Launching ${getDisplayPath(target)} on ${device.device.name} in $modeName mode...');
|
||||
final String effectiveHostname = debuggingOptions.hostname ?? 'localhost';
|
||||
final int hostPort = debuggingOptions.port == null
|
||||
? await os.findFreePort()
|
||||
@ -591,9 +587,7 @@ class _DwdsResidentWebRunner extends ResidentWebRunner {
|
||||
}
|
||||
final String modeName = debuggingOptions.buildInfo.friendlyModeName;
|
||||
globals.printStatus(
|
||||
'Launching ${fsUtils.getDisplayPath(target)} '
|
||||
'on ${device.device.name} in $modeName mode...',
|
||||
);
|
||||
'Launching ${getDisplayPath(target)} on ${device.device.name} in $modeName mode...');
|
||||
Status buildStatus;
|
||||
bool statusActive = false;
|
||||
try {
|
||||
|
@ -82,23 +82,14 @@ class BuildRunnerWebCompilationProxy extends WebCompilationProxy {
|
||||
.listSync()
|
||||
.whereType<Directory>();
|
||||
for (final Directory childDirectory in childDirectories) {
|
||||
final String path = globals.fs.path.join(
|
||||
testOutputDir,
|
||||
'packages',
|
||||
globals.fs.path.basename(childDirectory.path),
|
||||
);
|
||||
fsUtils.copyDirectorySync(
|
||||
childDirectory.childDirectory('lib'),
|
||||
globals.fs.directory(path),
|
||||
);
|
||||
final String path = globals.fs.path.join(testOutputDir, 'packages',
|
||||
globals.fs.path.basename(childDirectory.path));
|
||||
copyDirectorySync(childDirectory.childDirectory('lib'), globals.fs.directory(path));
|
||||
}
|
||||
final Directory outputDirectory = rootDirectory
|
||||
.childDirectory(projectName)
|
||||
.childDirectory('test');
|
||||
fsUtils.copyDirectorySync(
|
||||
outputDirectory,
|
||||
globals.fs.directory(globals.fs.path.join(testOutputDir)),
|
||||
);
|
||||
.childDirectory(projectName)
|
||||
.childDirectory('test');
|
||||
copyDirectorySync(outputDirectory, globals.fs.directory(globals.fs.path.join(testOutputDir)));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ class FlutterPlugins extends Target {
|
||||
final FlutterProject project = FlutterProject.fromDirectory(environment.projectDir);
|
||||
final List<Plugin> plugins = findPlugins(project);
|
||||
final String pluginManifest = plugins
|
||||
.map<String>((Plugin p) => '${p.name}=${fsUtils.escapePath(p.path)}')
|
||||
.join('\n');
|
||||
.map<String>((Plugin p) => '${p.name}=${escapePath(p.path)}')
|
||||
.join('\n');
|
||||
final File flutterPluginsFile = environment.projectDir.childFile('.flutter-plugins');
|
||||
if (!flutterPluginsFile.existsSync() || flutterPluginsFile.readAsStringSync() != pluginManifest) {
|
||||
flutterPluginsFile.writeAsStringSync(pluginManifest);
|
||||
|
@ -346,10 +346,7 @@ class Cache {
|
||||
/// [entity] doesn't exist.
|
||||
bool isOlderThanToolsStamp(FileSystemEntity entity) {
|
||||
final File flutterToolsStamp = getStampFileFor('flutter_tools');
|
||||
return fsUtils.isOlderThanReference(
|
||||
entity: entity,
|
||||
referenceFile: flutterToolsStamp,
|
||||
);
|
||||
return isOlderThanReference(entity: entity, referenceFile: flutterToolsStamp);
|
||||
}
|
||||
|
||||
bool isUpToDate() => _artifacts.every((ArtifactSet artifact) => artifact.isUpToDate());
|
||||
@ -915,7 +912,7 @@ class AndroidMavenArtifacts extends ArtifactSet {
|
||||
);
|
||||
try {
|
||||
final String gradleExecutable = gradle.absolute.path;
|
||||
final String flutterSdk = fsUtils.escapePath(Cache.flutterRoot);
|
||||
final String flutterSdk = escapePath(Cache.flutterRoot);
|
||||
final RunResult processResult = await processUtils.run(
|
||||
<String>[
|
||||
gradleExecutable,
|
||||
|
@ -11,6 +11,7 @@ import '../base/common.dart';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../cache.dart';
|
||||
import '../commands/daemon.dart';
|
||||
import '../compile.dart';
|
||||
|
@ -265,35 +265,15 @@ end
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _produceFlutterFramework(
|
||||
Directory outputDirectory,
|
||||
BuildMode mode,
|
||||
Directory iPhoneBuildOutput,
|
||||
Directory simulatorBuildOutput,
|
||||
Directory modeDirectory,
|
||||
) async {
|
||||
final Status status = globals.logger.startProgress(
|
||||
' ├─Populating Flutter.framework...',
|
||||
timeout: timeoutConfiguration.slowOperation,
|
||||
);
|
||||
final String engineCacheFlutterFrameworkDirectory = globals.artifacts.getArtifactPath(
|
||||
Artifact.flutterFramework,
|
||||
platform: TargetPlatform.ios,
|
||||
mode: mode,
|
||||
);
|
||||
final String flutterFrameworkFileName = globals.fs.path.basename(
|
||||
engineCacheFlutterFrameworkDirectory,
|
||||
);
|
||||
final Directory fatFlutterFrameworkCopy = modeDirectory.childDirectory(
|
||||
flutterFrameworkFileName,
|
||||
);
|
||||
Future<void> _produceFlutterFramework(Directory outputDirectory, BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
|
||||
final Status status = globals.logger.startProgress(' ├─Populating Flutter.framework...', timeout: timeoutConfiguration.slowOperation);
|
||||
final String engineCacheFlutterFrameworkDirectory = globals.artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: mode);
|
||||
final String flutterFrameworkFileName = globals.fs.path.basename(engineCacheFlutterFrameworkDirectory);
|
||||
final Directory fatFlutterFrameworkCopy = modeDirectory.childDirectory(flutterFrameworkFileName);
|
||||
|
||||
try {
|
||||
// Copy universal engine cache framework to mode directory.
|
||||
fsUtils.copyDirectorySync(
|
||||
globals.fs.directory(engineCacheFlutterFrameworkDirectory),
|
||||
fatFlutterFrameworkCopy,
|
||||
);
|
||||
copyDirectorySync(globals.fs.directory(engineCacheFlutterFrameworkDirectory), fatFlutterFrameworkCopy);
|
||||
|
||||
if (mode != BuildMode.debug) {
|
||||
final File fatFlutterFrameworkBinary = fatFlutterFrameworkCopy.childFile('Flutter');
|
||||
@ -315,8 +295,7 @@ end
|
||||
|
||||
if (lipoResult.exitCode != 0) {
|
||||
throwToolExit(
|
||||
'Unable to remove simulator architecture in $mode: ${lipoResult.stderr}',
|
||||
);
|
||||
'Unable to remove simulator architecture in $mode: ${lipoResult.stderr}');
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@ -399,18 +378,12 @@ end
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _produceAotAppFrameworkIfNeeded(
|
||||
BuildMode mode,
|
||||
Directory iPhoneBuildOutput,
|
||||
Directory destinationAppFrameworkDirectory,
|
||||
) async {
|
||||
Future<void> _produceAotAppFrameworkIfNeeded(BuildMode mode, Directory iPhoneBuildOutput, Directory destinationAppFrameworkDirectory) async {
|
||||
if (mode == BuildMode.debug) {
|
||||
return;
|
||||
}
|
||||
final Status status = globals.logger.startProgress(
|
||||
' ├─Building Dart AOT for App.framework...',
|
||||
timeout: timeoutConfiguration.slowOperation,
|
||||
);
|
||||
' ├─Building Dart AOT for App.framework...', timeout: timeoutConfiguration.slowOperation);
|
||||
try {
|
||||
await aotBuilder.build(
|
||||
platform: TargetPlatform.ios,
|
||||
@ -426,10 +399,7 @@ end
|
||||
);
|
||||
|
||||
const String appFrameworkName = 'App.framework';
|
||||
fsUtils.copyDirectorySync(
|
||||
iPhoneBuildOutput.childDirectory(appFrameworkName),
|
||||
destinationAppFrameworkDirectory,
|
||||
);
|
||||
copyDirectorySync(iPhoneBuildOutput.childDirectory(appFrameworkName), destinationAppFrameworkDirectory);
|
||||
} finally {
|
||||
status.stop();
|
||||
}
|
||||
@ -486,96 +456,72 @@ end
|
||||
buildPluginsResult = processUtils.runSync(
|
||||
pluginsBuildCommand,
|
||||
workingDirectory: _project.ios.hostAppRoot
|
||||
.childDirectory('Pods')
|
||||
.path,
|
||||
.childDirectory('Pods')
|
||||
.path,
|
||||
allowReentrantFlutter: false,
|
||||
);
|
||||
|
||||
if (buildPluginsResult.exitCode != 0) {
|
||||
throwToolExit(
|
||||
'Unable to build plugin frameworks for simulator: ${buildPluginsResult.stderr}',
|
||||
);
|
||||
throwToolExit('Unable to build plugin frameworks for simulator: ${buildPluginsResult.stderr}');
|
||||
}
|
||||
}
|
||||
|
||||
final Directory iPhoneBuildConfiguration = iPhoneBuildOutput.childDirectory(
|
||||
'$xcodeBuildConfiguration-iphoneos',
|
||||
);
|
||||
final Directory simulatorBuildConfiguration = simulatorBuildOutput.childDirectory(
|
||||
'$xcodeBuildConfiguration-iphonesimulator',
|
||||
);
|
||||
final Directory iPhoneBuildConfiguration = iPhoneBuildOutput.childDirectory('$xcodeBuildConfiguration-iphoneos');
|
||||
final Directory simulatorBuildConfiguration = simulatorBuildOutput.childDirectory('$xcodeBuildConfiguration-iphonesimulator');
|
||||
|
||||
final Iterable<Directory> products = iPhoneBuildConfiguration
|
||||
.listSync(followLinks: false)
|
||||
.whereType<Directory>();
|
||||
for (final Directory builtProduct in products) {
|
||||
for (final Directory builtProduct in iPhoneBuildConfiguration.listSync(followLinks: false).whereType<Directory>()) {
|
||||
for (final FileSystemEntity podProduct in builtProduct.listSync(followLinks: false)) {
|
||||
final String podFrameworkName = podProduct.basename;
|
||||
if (globals.fs.path.extension(podFrameworkName) != '.framework') {
|
||||
continue;
|
||||
}
|
||||
final String binaryName = globals.fs.path.basenameWithoutExtension(podFrameworkName);
|
||||
if (boolArg('universal')) {
|
||||
fsUtils.copyDirectorySync(
|
||||
podProduct as Directory,
|
||||
modeDirectory.childDirectory(podFrameworkName),
|
||||
);
|
||||
final List<String> lipoCommand = <String>[
|
||||
'xcrun',
|
||||
'lipo',
|
||||
'-create',
|
||||
globals.fs.path.join(podProduct.path, binaryName),
|
||||
if (mode == BuildMode.debug)
|
||||
simulatorBuildConfiguration
|
||||
.childDirectory(binaryName)
|
||||
.childDirectory(podFrameworkName)
|
||||
.childFile(binaryName)
|
||||
.path,
|
||||
'-output',
|
||||
modeDirectory.childDirectory(podFrameworkName).childFile(binaryName).path
|
||||
];
|
||||
if (globals.fs.path.extension(podFrameworkName) == '.framework') {
|
||||
final String binaryName = globals.fs.path.basenameWithoutExtension(podFrameworkName);
|
||||
if (boolArg('universal')) {
|
||||
copyDirectorySync(podProduct as Directory, modeDirectory.childDirectory(podFrameworkName));
|
||||
final List<String> lipoCommand = <String>[
|
||||
'xcrun',
|
||||
'lipo',
|
||||
'-create',
|
||||
globals.fs.path.join(podProduct.path, binaryName),
|
||||
if (mode == BuildMode.debug)
|
||||
simulatorBuildConfiguration.childDirectory(binaryName).childDirectory(podFrameworkName).childFile(binaryName).path,
|
||||
'-output',
|
||||
modeDirectory.childDirectory(podFrameworkName).childFile(binaryName).path
|
||||
];
|
||||
|
||||
final RunResult pluginsLipoResult = processUtils.runSync(
|
||||
lipoCommand,
|
||||
workingDirectory: outputDirectory.path,
|
||||
allowReentrantFlutter: false,
|
||||
);
|
||||
|
||||
if (pluginsLipoResult.exitCode != 0) {
|
||||
throwToolExit(
|
||||
'Unable to create universal $binaryName.framework: ${buildPluginsResult.stderr}',
|
||||
final RunResult pluginsLipoResult = processUtils.runSync(
|
||||
lipoCommand,
|
||||
workingDirectory: outputDirectory.path,
|
||||
allowReentrantFlutter: false,
|
||||
);
|
||||
|
||||
if (pluginsLipoResult.exitCode != 0) {
|
||||
throwToolExit('Unable to create universal $binaryName.framework: ${buildPluginsResult.stderr}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (boolArg('xcframework')) {
|
||||
final List<String> xcframeworkCommand = <String>[
|
||||
'xcrun',
|
||||
'xcodebuild',
|
||||
'-create-xcframework',
|
||||
'-framework',
|
||||
podProduct.path,
|
||||
if (mode == BuildMode.debug)
|
||||
if (boolArg('xcframework')) {
|
||||
final List<String> xcframeworkCommand = <String>[
|
||||
'xcrun',
|
||||
'xcodebuild',
|
||||
'-create-xcframework',
|
||||
'-framework',
|
||||
if (mode == BuildMode.debug)
|
||||
simulatorBuildConfiguration
|
||||
.childDirectory(binaryName)
|
||||
.childDirectory(podFrameworkName)
|
||||
.path,
|
||||
'-output',
|
||||
modeDirectory.childFile('$binaryName.xcframework').path
|
||||
];
|
||||
podProduct.path,
|
||||
if (mode == BuildMode.debug)
|
||||
'-framework',
|
||||
if (mode == BuildMode.debug)
|
||||
simulatorBuildConfiguration.childDirectory(binaryName).childDirectory(podFrameworkName).path,
|
||||
'-output',
|
||||
modeDirectory.childFile('$binaryName.xcframework').path
|
||||
];
|
||||
|
||||
final RunResult xcframeworkResult = processUtils.runSync(
|
||||
xcframeworkCommand,
|
||||
workingDirectory: outputDirectory.path,
|
||||
allowReentrantFlutter: false,
|
||||
);
|
||||
|
||||
if (xcframeworkResult.exitCode != 0) {
|
||||
throwToolExit(
|
||||
'Unable to create $binaryName.xcframework: ${xcframeworkResult.stderr}',
|
||||
final RunResult xcframeworkResult = processUtils.runSync(
|
||||
xcframeworkCommand,
|
||||
workingDirectory: outputDirectory.path,
|
||||
allowReentrantFlutter: false,
|
||||
);
|
||||
|
||||
if (xcframeworkResult.exitCode != 0) {
|
||||
throwToolExit('Unable to create $binaryName.xcframework: ${xcframeworkResult.stderr}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -590,10 +536,7 @@ end
|
||||
final String frameworkBinaryName = globals.fs.path.basenameWithoutExtension(
|
||||
fatFramework.basename);
|
||||
|
||||
final Status status = globals.logger.startProgress(
|
||||
' ├─Creating $frameworkBinaryName.xcframework...',
|
||||
timeout: timeoutConfiguration.fastOperation,
|
||||
);
|
||||
final Status status = globals.logger.startProgress(' ├─Creating $frameworkBinaryName.xcframework...', timeout: timeoutConfiguration.fastOperation);
|
||||
try {
|
||||
if (mode == BuildMode.debug) {
|
||||
_produceDebugXCFramework(fatFramework, frameworkBinaryName);
|
||||
@ -613,24 +556,22 @@ end
|
||||
void _produceDebugXCFramework(Directory fatFramework, String frameworkBinaryName) {
|
||||
final String frameworkFileName = fatFramework.basename;
|
||||
final File fatFlutterFrameworkBinary = fatFramework.childFile(
|
||||
frameworkBinaryName,
|
||||
);
|
||||
frameworkBinaryName);
|
||||
final Directory temporaryOutput = globals.fs.systemTempDirectory.createTempSync(
|
||||
'flutter_tool_build_ios_framework.',
|
||||
);
|
||||
'flutter_tool_build_ios_framework.');
|
||||
try {
|
||||
// Copy universal framework to variant directory.
|
||||
final Directory iPhoneBuildOutput = temporaryOutput.childDirectory(
|
||||
'ios',
|
||||
)..createSync(recursive: true);
|
||||
'ios')
|
||||
..createSync(recursive: true);
|
||||
final Directory simulatorBuildOutput = temporaryOutput.childDirectory(
|
||||
'simulator',
|
||||
)..createSync(recursive: true);
|
||||
'simulator')
|
||||
..createSync(recursive: true);
|
||||
final Directory armFlutterFrameworkDirectory = iPhoneBuildOutput
|
||||
.childDirectory(frameworkFileName);
|
||||
.childDirectory(frameworkFileName);
|
||||
final File armFlutterFrameworkBinary = armFlutterFrameworkDirectory
|
||||
.childFile(frameworkBinaryName);
|
||||
fsUtils.copyDirectorySync(fatFramework, armFlutterFrameworkDirectory);
|
||||
.childFile(frameworkBinaryName);
|
||||
copyDirectorySync(fatFramework, armFlutterFrameworkDirectory);
|
||||
|
||||
// Create iOS framework.
|
||||
List<String> lipoCommand = <String>[
|
||||
@ -654,10 +595,10 @@ end
|
||||
|
||||
// Create simulator framework.
|
||||
final Directory simulatorFlutterFrameworkDirectory = simulatorBuildOutput
|
||||
.childDirectory(frameworkFileName);
|
||||
.childDirectory(frameworkFileName);
|
||||
final File simulatorFlutterFrameworkBinary = simulatorFlutterFrameworkDirectory
|
||||
.childFile(frameworkBinaryName);
|
||||
fsUtils.copyDirectorySync(fatFramework, simulatorFlutterFrameworkDirectory);
|
||||
.childFile(frameworkBinaryName);
|
||||
copyDirectorySync(fatFramework, simulatorFlutterFrameworkDirectory);
|
||||
|
||||
lipoCommand = <String>[
|
||||
'xcrun',
|
||||
@ -698,19 +639,14 @@ end
|
||||
|
||||
if (xcframeworkResult.exitCode != 0) {
|
||||
throwToolExit(
|
||||
'Unable to create XCFramework: ${xcframeworkResult.stderr}',
|
||||
);
|
||||
'Unable to create XCFramework: ${xcframeworkResult.stderr}');
|
||||
}
|
||||
} finally {
|
||||
temporaryOutput.deleteSync(recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
void _produceNonDebugXCFramework(
|
||||
BuildMode mode,
|
||||
Directory fatFramework,
|
||||
String frameworkBinaryName,
|
||||
) {
|
||||
void _produceNonDebugXCFramework(BuildMode mode, Directory fatFramework, String frameworkBinaryName) {
|
||||
// Simulator is only supported in Debug mode.
|
||||
// "Fat" framework here must only contain arm.
|
||||
final List<String> xcframeworkCommand = <String>[
|
||||
|
@ -650,7 +650,7 @@ To edit platform code in an IDE see https://flutter.dev/developing-packages/#edi
|
||||
|
||||
int _injectGradleWrapper(FlutterProject project) {
|
||||
int filesCreated = 0;
|
||||
fsUtils.copyDirectorySync(
|
||||
copyDirectorySync(
|
||||
globals.cache.getArtifactDirectory('gradle_wrapper'),
|
||||
project.android.hostAppGradleRoot,
|
||||
onFileCopied: (File sourceFile, File destinationFile) {
|
||||
|
@ -8,7 +8,6 @@ import 'package:args/command_runner.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/time.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
|
@ -6,6 +6,7 @@ import 'dart:async';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../convert.dart';
|
||||
import '../device.dart';
|
||||
import '../globals.dart' as globals;
|
||||
@ -109,11 +110,7 @@ class ScreenshotCommand extends FlutterCommand {
|
||||
}
|
||||
|
||||
Future<void> runScreenshot(File outputFile) async {
|
||||
outputFile ??= fsUtils.getUniqueFile(
|
||||
globals.fs.currentDirectory,
|
||||
'flutter',
|
||||
'png',
|
||||
);
|
||||
outputFile ??= getUniqueFile(globals.fs.currentDirectory, 'flutter', 'png');
|
||||
try {
|
||||
await device.takeScreenshot(outputFile);
|
||||
} catch (error) {
|
||||
@ -124,11 +121,7 @@ class ScreenshotCommand extends FlutterCommand {
|
||||
|
||||
Future<void> runSkia(File outputFile) async {
|
||||
final Map<String, dynamic> skp = await _invokeVmServiceRpc('_flutter.screenshotSkp');
|
||||
outputFile ??= fsUtils.getUniqueFile(
|
||||
globals.fs.currentDirectory,
|
||||
'flutter',
|
||||
'skp',
|
||||
);
|
||||
outputFile ??= getUniqueFile(globals.fs.currentDirectory, 'flutter', 'skp');
|
||||
final IOSink sink = outputFile.openWrite();
|
||||
sink.add(base64.decode(skp['skp'] as String));
|
||||
await sink.close();
|
||||
@ -138,11 +131,7 @@ class ScreenshotCommand extends FlutterCommand {
|
||||
|
||||
Future<void> runRasterizer(File outputFile) async {
|
||||
final Map<String, dynamic> response = await _invokeVmServiceRpc('_flutter.screenshot');
|
||||
outputFile ??= fsUtils.getUniqueFile(
|
||||
globals.fs.currentDirectory,
|
||||
'flutter',
|
||||
'png',
|
||||
);
|
||||
outputFile ??= getUniqueFile(globals.fs.currentDirectory, 'flutter', 'png');
|
||||
final IOSink sink = outputFile.openWrite();
|
||||
sink.add(base64.decode(response['screenshot'] as String));
|
||||
await sink.close();
|
||||
|
@ -189,7 +189,7 @@ class ArtifactUnpacker {
|
||||
final String sourcePath = globals.fs.path.join(sourceDirectory, entityName);
|
||||
final String targetPath = globals.fs.path.join(targetDirectory, entityName);
|
||||
if (entityName.endsWith('/')) {
|
||||
fsUtils.copyDirectorySync(
|
||||
copyDirectorySync(
|
||||
globals.fs.directory(sourcePath),
|
||||
globals.fs.directory(targetPath),
|
||||
);
|
||||
|
@ -551,10 +551,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
// (for example, kernel binary files produced from previous run).
|
||||
globals.fs.directory(outputDir).deleteSync(recursive: true);
|
||||
}
|
||||
fsUtils.copyDirectorySync(
|
||||
globals.fs.directory(expectedOutputDirectory),
|
||||
globals.fs.directory(outputDir),
|
||||
);
|
||||
copyDirectorySync(globals.fs.directory(expectedOutputDirectory), globals.fs.directory(outputDir));
|
||||
} else {
|
||||
globals.printError('Build succeeded but the expected app at $expectedOutputDirectory not found');
|
||||
}
|
||||
|
@ -25,10 +25,7 @@ abstract class PersistentToolState {
|
||||
|
||||
class _DefaultPersistentToolState implements PersistentToolState {
|
||||
_DefaultPersistentToolState([File configFile]) :
|
||||
_config = Config(configFile ?? globals.fs.file(globals.fs.path.join(
|
||||
fsUtils.userHomePath,
|
||||
_kFileName,
|
||||
)));
|
||||
_config = Config(configFile ?? globals.fs.file(globals.fs.path.join(userHomePath(), _kFileName)));
|
||||
|
||||
static const String _kFileName = '.flutter_tool_state';
|
||||
static const String _kRedisplayWelcomeMessage = 'redisplay-welcome-message';
|
||||
|
@ -325,7 +325,7 @@ bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
|
||||
pluginNames.add(plugin.name);
|
||||
}
|
||||
for (final Plugin plugin in plugins) {
|
||||
flutterPluginsBuffer.write('${plugin.name}=${fsUtils.escapePath(plugin.path)}\n');
|
||||
flutterPluginsBuffer.write('${plugin.name}=${escapePath(plugin.path)}\n');
|
||||
directAppDependencies.add(<String, dynamic>{
|
||||
'name': plugin.name,
|
||||
// Extract the plugin dependencies which happen to be plugins.
|
||||
|
@ -467,10 +467,7 @@ class IosProject implements XcodeBasedProject {
|
||||
if (!isModule) {
|
||||
return;
|
||||
}
|
||||
final bool pubspecChanged = fsUtils.isOlderThanReference(
|
||||
entity: ephemeralDirectory,
|
||||
referenceFile: parent.pubspecFile,
|
||||
);
|
||||
final bool pubspecChanged = isOlderThanReference(entity: ephemeralDirectory, referenceFile: parent.pubspecFile);
|
||||
final bool toolingChanged = globals.cache.isOlderThanToolsStamp(ephemeralDirectory);
|
||||
if (!pubspecChanged && !toolingChanged) {
|
||||
return;
|
||||
@ -481,37 +478,22 @@ class IosProject implements XcodeBasedProject {
|
||||
.childDirectory('engine');
|
||||
|
||||
_deleteIfExistsSync(ephemeralDirectory);
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'library'),
|
||||
ephemeralDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'library'), ephemeralDirectory);
|
||||
// Add ephemeral host app, if a editable host app does not already exist.
|
||||
if (!_editableDirectory.existsSync()) {
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'host_app_ephemeral'),
|
||||
ephemeralDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'host_app_ephemeral'), ephemeralDirectory);
|
||||
if (hasPlugins(parent)) {
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'),
|
||||
ephemeralDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'), ephemeralDirectory);
|
||||
}
|
||||
// Copy podspec and framework from engine cache. The actual build mode
|
||||
// doesn't actually matter as it will be overwritten by xcode_backend.sh.
|
||||
// However, cocoapods will run before that script and requires something
|
||||
// to be in this location.
|
||||
final Directory framework = globals.fs.directory(
|
||||
globals.artifacts.getArtifactPath(Artifact.flutterFramework,
|
||||
platform: TargetPlatform.ios,
|
||||
mode: BuildMode.debug,
|
||||
));
|
||||
final Directory framework = globals.fs.directory(globals.artifacts.getArtifactPath(Artifact.flutterFramework,
|
||||
platform: TargetPlatform.ios, mode: BuildMode.debug));
|
||||
if (framework.existsSync()) {
|
||||
final File podspec = framework.parent.childFile('Flutter.podspec');
|
||||
fsUtils.copyDirectorySync(
|
||||
framework,
|
||||
engineDest.childDirectory('Flutter.framework'),
|
||||
);
|
||||
copyDirectorySync(framework, engineDest.childDirectory('Flutter.framework'));
|
||||
podspec.copySync(engineDest.childFile('Flutter.podspec').path);
|
||||
}
|
||||
}
|
||||
@ -523,36 +505,20 @@ class IosProject implements XcodeBasedProject {
|
||||
throwToolExit('iOS host app is already editable. To start fresh, delete the ios/ folder.');
|
||||
}
|
||||
_deleteIfExistsSync(ephemeralDirectory);
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'library'),
|
||||
ephemeralDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'host_app_ephemeral'),
|
||||
_editableDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'),
|
||||
_editableDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(
|
||||
globals.fs.path.join('module', 'ios', 'host_app_editable_cocoapods'),
|
||||
_editableDirectory,
|
||||
);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'library'), ephemeralDirectory);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'host_app_ephemeral'), _editableDirectory);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'), _editableDirectory);
|
||||
_overwriteFromTemplate(globals.fs.path.join('module', 'ios', 'host_app_editable_cocoapods'), _editableDirectory);
|
||||
await _updateGeneratedXcodeConfigIfNeeded();
|
||||
await injectPlugins(parent);
|
||||
}
|
||||
|
||||
@override
|
||||
File get generatedXcodePropertiesFile => _flutterLibRoot
|
||||
.childDirectory('Flutter')
|
||||
.childFile('Generated.xcconfig');
|
||||
File get generatedXcodePropertiesFile => _flutterLibRoot.childDirectory('Flutter').childFile('Generated.xcconfig');
|
||||
|
||||
Directory get pluginRegistrantHost {
|
||||
return isModule
|
||||
? _flutterLibRoot
|
||||
.childDirectory('Flutter')
|
||||
.childDirectory('FlutterPluginRegistrant')
|
||||
? _flutterLibRoot.childDirectory('Flutter').childDirectory('FlutterPluginRegistrant')
|
||||
: hostAppRoot.childDirectory(_hostAppBundleName);
|
||||
}
|
||||
|
||||
@ -666,10 +632,8 @@ class AndroidProject {
|
||||
}
|
||||
|
||||
bool _shouldRegenerateFromTemplate() {
|
||||
return fsUtils.isOlderThanReference(
|
||||
entity: ephemeralDirectory,
|
||||
referenceFile: parent.pubspecFile,
|
||||
) || globals.cache.isOlderThanToolsStamp(ephemeralDirectory);
|
||||
return isOlderThanReference(entity: ephemeralDirectory, referenceFile: parent.pubspecFile)
|
||||
|| globals.cache.isOlderThanToolsStamp(ephemeralDirectory);
|
||||
}
|
||||
|
||||
Future<void> makeHostAppEditable() async {
|
||||
|
@ -405,10 +405,7 @@ class FlutterDevice {
|
||||
}) async {
|
||||
final bool prebuiltMode = hotRunner.applicationBinary != null;
|
||||
final String modeName = hotRunner.debuggingOptions.buildInfo.friendlyModeName;
|
||||
globals.printStatus(
|
||||
'Launching ${fsUtils.getDisplayPath(hotRunner.mainPath)} '
|
||||
'on ${device.name} in $modeName mode...',
|
||||
);
|
||||
globals.printStatus('Launching ${getDisplayPath(hotRunner.mainPath)} on ${device.name} in $modeName mode...');
|
||||
|
||||
final TargetPlatform targetPlatform = await device.targetPlatform;
|
||||
package = await ApplicationPackageFactory.instance.getPackageForPlatform(
|
||||
@ -475,15 +472,9 @@ class FlutterDevice {
|
||||
final bool prebuiltMode = coldRunner.applicationBinary != null;
|
||||
if (coldRunner.mainPath == null) {
|
||||
assert(prebuiltMode);
|
||||
globals.printStatus(
|
||||
'Launching ${package.displayName} '
|
||||
'on ${device.name} in $modeName mode...',
|
||||
);
|
||||
globals.printStatus('Launching ${package.displayName} on ${device.name} in $modeName mode...');
|
||||
} else {
|
||||
globals.printStatus(
|
||||
'Launching ${fsUtils.getDisplayPath(coldRunner.mainPath)} '
|
||||
'on ${device.name} in $modeName mode...',
|
||||
);
|
||||
globals.printStatus('Launching ${getDisplayPath(coldRunner.mainPath)} on ${device.name} in $modeName mode...');
|
||||
}
|
||||
|
||||
if (package == null) {
|
||||
@ -858,15 +849,8 @@ abstract class ResidentRunner {
|
||||
Future<void> screenshot(FlutterDevice device) async {
|
||||
assert(device.device.supportsScreenshot);
|
||||
|
||||
final Status status = globals.logger.startProgress(
|
||||
'Taking screenshot for ${device.device.name}...',
|
||||
timeout: timeoutConfiguration.fastOperation,
|
||||
);
|
||||
final File outputFile = fsUtils.getUniqueFile(
|
||||
globals.fs.currentDirectory,
|
||||
'flutter',
|
||||
'png',
|
||||
);
|
||||
final Status status = globals.logger.startProgress('Taking screenshot for ${device.device.name}...', timeout: timeoutConfiguration.fastOperation);
|
||||
final File outputFile = getUniqueFile(globals.fs.currentDirectory, 'flutter', 'png');
|
||||
try {
|
||||
if (supportsServiceProtocol && isRunningDebug) {
|
||||
await device.refreshViews();
|
||||
@ -897,9 +881,7 @@ abstract class ResidentRunner {
|
||||
}
|
||||
final int sizeKB = outputFile.lengthSync() ~/ 1024;
|
||||
status.stop();
|
||||
globals.printStatus(
|
||||
'Screenshot written to ${globals.fs.path.relative(outputFile.path)} (${sizeKB}kB).',
|
||||
);
|
||||
globals.printStatus('Screenshot written to ${globals.fs.path.relative(outputFile.path)} (${sizeKB}kB).');
|
||||
} catch (error) {
|
||||
status.cancel();
|
||||
globals.printError('Error taking screenshot: $error');
|
||||
|
@ -160,7 +160,7 @@ class TestCompiler {
|
||||
// The idea is to keep the cache file up-to-date and include as
|
||||
// much as possible in an effort to re-use as many packages as
|
||||
// possible.
|
||||
fsUtils.ensureDirectoryExists(testFilePath);
|
||||
ensureDirectoryExists(testFilePath);
|
||||
await outputFile.copy(testFilePath);
|
||||
}
|
||||
request.result.complete(kernelReadyToRun.path);
|
||||
|
@ -4,41 +4,41 @@
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
|
||||
class MockPlatform extends Mock implements Platform {}
|
||||
import '../../src/context.dart';
|
||||
|
||||
void main() {
|
||||
group('ensureDirectoryExists', () {
|
||||
MemoryFileSystem fs;
|
||||
FileSystemUtils fsUtils;
|
||||
|
||||
setUp(() {
|
||||
fs = MemoryFileSystem();
|
||||
fsUtils = FileSystemUtils(
|
||||
fileSystem: fs,
|
||||
platform: MockPlatform(),
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('recursively creates a directory if it does not exist', () async {
|
||||
fsUtils.ensureDirectoryExists('foo/bar/baz.flx');
|
||||
testUsingContext('recursively creates a directory if it does not exist', () async {
|
||||
ensureDirectoryExists('foo/bar/baz.flx');
|
||||
expect(fs.isDirectorySync('foo/bar'), true);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testWithoutContext('throws tool exit on failure to create', () async {
|
||||
testUsingContext('throws tool exit on failure to create', () async {
|
||||
fs.file('foo').createSync();
|
||||
expect(() => fsUtils.ensureDirectoryExists('foo/bar.flx'), throwsToolExit());
|
||||
expect(() => ensureDirectoryExists('foo/bar.flx'), throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
});
|
||||
|
||||
group('copyDirectorySync', () {
|
||||
/// Test file_systems.copyDirectorySync() using MemoryFileSystem.
|
||||
/// Copies between 2 instances of file systems which is also supported by copyDirectorySync().
|
||||
testWithoutContext('test directory copy', () async {
|
||||
test('test directory copy', () async {
|
||||
final MemoryFileSystem sourceMemoryFs = MemoryFileSystem();
|
||||
const String sourcePath = '/some/origin';
|
||||
final Directory sourceDirectory = await sourceMemoryFs.directory(sourcePath).create(recursive: true);
|
||||
@ -52,12 +52,7 @@ void main() {
|
||||
final MemoryFileSystem targetMemoryFs = MemoryFileSystem();
|
||||
const String targetPath = '/some/non-existent/target';
|
||||
final Directory targetDirectory = targetMemoryFs.directory(targetPath);
|
||||
|
||||
final FileSystemUtils fsUtils = FileSystemUtils(
|
||||
fileSystem: sourceMemoryFs,
|
||||
platform: MockPlatform(),
|
||||
);
|
||||
fsUtils.copyDirectorySync(sourceDirectory, targetDirectory);
|
||||
copyDirectorySync(sourceDirectory, targetDirectory);
|
||||
|
||||
expect(targetDirectory.existsSync(), true);
|
||||
targetMemoryFs.currentDirectory = targetPath;
|
||||
@ -71,21 +66,16 @@ void main() {
|
||||
expect(sourceMemoryFs.directory(sourcePath).listSync().length, 3);
|
||||
});
|
||||
|
||||
testWithoutContext('Skip files if shouldCopyFile returns false', () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem();
|
||||
final FileSystemUtils fsUtils = FileSystemUtils(
|
||||
fileSystem: fileSystem,
|
||||
platform: MockPlatform(),
|
||||
);
|
||||
final Directory origin = fileSystem.directory('/origin');
|
||||
testUsingContext('Skip files if shouldCopyFile returns false', () {
|
||||
final Directory origin = globals.fs.directory('/origin');
|
||||
origin.createSync();
|
||||
fileSystem.file(fileSystem.path.join('origin', 'a.txt')).writeAsStringSync('irrelevant');
|
||||
fileSystem.directory('/origin/nested').createSync();
|
||||
fileSystem.file(fileSystem.path.join('origin', 'nested', 'a.txt')).writeAsStringSync('irrelevant');
|
||||
fileSystem.file(fileSystem.path.join('origin', 'nested', 'b.txt')).writeAsStringSync('irrelevant');
|
||||
globals.fs.file(globals.fs.path.join('origin', 'a.txt')).writeAsStringSync('irrelevant');
|
||||
globals.fs.directory('/origin/nested').createSync();
|
||||
globals.fs.file(globals.fs.path.join('origin', 'nested', 'a.txt')).writeAsStringSync('irrelevant');
|
||||
globals.fs.file(globals.fs.path.join('origin', 'nested', 'b.txt')).writeAsStringSync('irrelevant');
|
||||
|
||||
final Directory destination = fileSystem.directory('/destination');
|
||||
fsUtils.copyDirectorySync(origin, destination, shouldCopyFile: (File origin, File dest) {
|
||||
final Directory destination = globals.fs.directory('/destination');
|
||||
copyDirectorySync(origin, destination, shouldCopyFile: (File origin, File dest) {
|
||||
return origin.basename == 'b.txt';
|
||||
});
|
||||
|
||||
@ -95,30 +85,53 @@ void main() {
|
||||
|
||||
expect(destination.childFile('a.txt').existsSync(), isFalse);
|
||||
expect(destination.childDirectory('nested').childFile('a.txt').existsSync(), isFalse);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => MemoryFileSystem(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
});
|
||||
|
||||
group('canonicalizePath', () {
|
||||
test('does not lowercase on Windows', () {
|
||||
String path = 'C:\\Foo\\bAr\\cOOL.dart';
|
||||
expect(canonicalizePath(path), path);
|
||||
// globals.fs.path.canonicalize does lowercase on Windows
|
||||
expect(globals.fs.path.canonicalize(path), isNot(path));
|
||||
|
||||
path = '..\\bar\\.\\\\Foo';
|
||||
final String expected = globals.fs.path.join(globals.fs.currentDirectory.parent.absolute.path, 'bar', 'Foo');
|
||||
expect(canonicalizePath(path), expected);
|
||||
// globals.fs.path.canonicalize should return the same result (modulo casing)
|
||||
expect(globals.fs.path.canonicalize(path), expected.toLowerCase());
|
||||
}, testOn: 'windows');
|
||||
|
||||
test('does not lowercase on posix', () {
|
||||
String path = '/Foo/bAr/cOOL.dart';
|
||||
expect(canonicalizePath(path), path);
|
||||
// globals.fs.path.canonicalize and canonicalizePath should be the same on Posix
|
||||
expect(globals.fs.path.canonicalize(path), path);
|
||||
|
||||
path = '../bar/.//Foo';
|
||||
final String expected = globals.fs.path.join(globals.fs.currentDirectory.parent.absolute.path, 'bar', 'Foo');
|
||||
expect(canonicalizePath(path), expected);
|
||||
}, testOn: 'posix');
|
||||
});
|
||||
|
||||
group('escapePath', () {
|
||||
testWithoutContext('on Windows', () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem();
|
||||
final FileSystemUtils fsUtils = FileSystemUtils(
|
||||
fileSystem: fileSystem,
|
||||
platform: FakePlatform(operatingSystem: 'windows'),
|
||||
);
|
||||
expect(fsUtils.escapePath('C:\\foo\\bar\\cool.dart'), 'C:\\\\foo\\\\bar\\\\cool.dart');
|
||||
expect(fsUtils.escapePath('foo\\bar\\cool.dart'), 'foo\\\\bar\\\\cool.dart');
|
||||
expect(fsUtils.escapePath('C:/foo/bar/cool.dart'), 'C:/foo/bar/cool.dart');
|
||||
testUsingContext('on Windows', () {
|
||||
expect(escapePath('C:\\foo\\bar\\cool.dart'), 'C:\\\\foo\\\\bar\\\\cool.dart');
|
||||
expect(escapePath('foo\\bar\\cool.dart'), 'foo\\\\bar\\\\cool.dart');
|
||||
expect(escapePath('C:/foo/bar/cool.dart'), 'C:/foo/bar/cool.dart');
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => FakePlatform(operatingSystem: 'windows'),
|
||||
});
|
||||
|
||||
testWithoutContext('on Linux', () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem();
|
||||
final FileSystemUtils fsUtils = FileSystemUtils(
|
||||
fileSystem: fileSystem,
|
||||
platform: FakePlatform(operatingSystem: 'linux'),
|
||||
);
|
||||
expect(fsUtils.escapePath('/foo/bar/cool.dart'), '/foo/bar/cool.dart');
|
||||
expect(fsUtils.escapePath('foo/bar/cool.dart'), 'foo/bar/cool.dart');
|
||||
expect(fsUtils.escapePath('foo\\cool.dart'), 'foo\\cool.dart');
|
||||
testUsingContext('on Linux', () {
|
||||
expect(escapePath('/foo/bar/cool.dart'), '/foo/bar/cool.dart');
|
||||
expect(escapePath('foo/bar/cool.dart'), 'foo/bar/cool.dart');
|
||||
expect(escapePath('foo\\cool.dart'), 'foo\\cool.dart');
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => FakePlatform(operatingSystem: 'linux'),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user