mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

I got tired of drive-by spelling fixes, so I figured I'd just take care of them all at once. This only corrects errors in the dartdocs, not regular comments, and I skipped any sample code in the dartdocs. It doesn't touch any identifiers in the dartdocs either. No code changes, just comments.
154 lines
6.1 KiB
Dart
154 lines
6.1 KiB
Dart
// 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.
|
|
|
|
import 'package:file/file.dart';
|
|
import 'package:file/local.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:file/record_replay.dart';
|
|
|
|
|
|
import 'common.dart' show throwToolExit;
|
|
import 'context.dart';
|
|
import 'platform.dart';
|
|
import 'process.dart';
|
|
|
|
export 'package:file/file.dart';
|
|
export 'package:file/local.dart';
|
|
|
|
const String _kRecordingType = 'file';
|
|
const FileSystem _kLocalFs = const LocalFileSystem();
|
|
|
|
/// Currently active implementation of the file system.
|
|
///
|
|
/// By default it uses local disk-based implementation. Override this in tests
|
|
/// with [MemoryFileSystem].
|
|
FileSystem get fs => context == null ? _kLocalFs : context[FileSystem];
|
|
|
|
/// Enables recording of file system activity to the specified base recording
|
|
/// [location].
|
|
///
|
|
/// This sets the [active file system](fs) to one that records all invocation
|
|
/// activity before delegating to a [LocalFileSystem].
|
|
///
|
|
/// Activity will be recorded in a subdirectory of [location] named `"file"`.
|
|
/// It is permissible for [location] to represent an existing non-empty
|
|
/// directory as long as there is no collision with the `"file"` subdirectory.
|
|
void enableRecordingFileSystem(String location) {
|
|
final FileSystem originalFileSystem = fs;
|
|
final Directory dir = getRecordingSink(location, _kRecordingType);
|
|
final RecordingFileSystem fileSystem = new RecordingFileSystem(
|
|
delegate: _kLocalFs, destination: dir);
|
|
addShutdownHook(() async {
|
|
await fileSystem.recording.flush();
|
|
context.setVariable(FileSystem, originalFileSystem);
|
|
}, ShutdownStage.SERIALIZE_RECORDING);
|
|
context.setVariable(FileSystem, fileSystem);
|
|
}
|
|
|
|
/// Enables file system replay mode.
|
|
///
|
|
/// This sets the [active file system](fs) to one that replays invocation
|
|
/// activity from a previously recorded set of invocations.
|
|
///
|
|
/// [location] must represent a directory to which file system activity has
|
|
/// been recorded (i.e. the result of having been previously passed to
|
|
/// [enableRecordingFileSystem]), or a [ToolExit] will be thrown.
|
|
void enableReplayFileSystem(String location) {
|
|
final Directory dir = getReplaySource(location, _kRecordingType);
|
|
context.setVariable(FileSystem, new ReplayFileSystem(recording: dir));
|
|
}
|
|
|
|
/// Create the ancestor directories of a file path if they do not already exist.
|
|
void ensureDirectoryExists(String filePath) {
|
|
final String dirPath = fs.path.dirname(filePath);
|
|
if (fs.isDirectorySync(dirPath))
|
|
return;
|
|
try {
|
|
fs.directory(dirPath).createSync(recursive: true);
|
|
} on FileSystemException catch (e) {
|
|
throwToolExit('Failed to create directory "$dirPath": ${e.osError.message}');
|
|
}
|
|
}
|
|
|
|
/// Recursively copies `srcDir` to `destDir`, invoking [onFileCopied] if
|
|
/// specified for each source/destination file pair.
|
|
///
|
|
/// Creates `destDir` if needed.
|
|
void copyDirectorySync(Directory srcDir, Directory destDir, [void onFileCopied(File srcFile, File destFile)]) {
|
|
if (!srcDir.existsSync())
|
|
throw new Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
|
|
|
|
if (!destDir.existsSync())
|
|
destDir.createSync(recursive: true);
|
|
|
|
for (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);
|
|
newFile.writeAsBytesSync(entity.readAsBytesSync());
|
|
onFileCopied?.call(entity, newFile);
|
|
} else if (entity is Directory) {
|
|
copyDirectorySync(
|
|
entity, destDir.fileSystem.directory(newPath));
|
|
} else {
|
|
throw new Exception('${entity.path} is neither File nor Directory');
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Gets a directory to act as a recording destination, creating the directory
|
|
/// as necessary.
|
|
///
|
|
/// The directory will exist in the local file system, be named [basename], and
|
|
/// be a child of the directory identified by [dirname].
|
|
///
|
|
/// If the target directory already exists as a directory, the existing
|
|
/// directory must be empty, or a [ToolExit] will be thrown. If the target
|
|
/// directory exists as an entity other than a directory, a [ToolExit] will
|
|
/// also be thrown.
|
|
Directory getRecordingSink(String dirname, String basename) {
|
|
final String location = _kLocalFs.path.join(dirname, basename);
|
|
switch (_kLocalFs.typeSync(location, followLinks: false)) {
|
|
case FileSystemEntityType.FILE:
|
|
case FileSystemEntityType.LINK:
|
|
throwToolExit('Invalid record-to location: $dirname ("$basename" exists as non-directory)');
|
|
break;
|
|
case FileSystemEntityType.DIRECTORY:
|
|
if (_kLocalFs.directory(location).listSync(followLinks: false).isNotEmpty)
|
|
throwToolExit('Invalid record-to location: $dirname ("$basename" is not empty)');
|
|
break;
|
|
case FileSystemEntityType.NOT_FOUND:
|
|
_kLocalFs.directory(location).createSync(recursive: true);
|
|
}
|
|
return _kLocalFs.directory(location);
|
|
}
|
|
|
|
/// Gets a directory that holds a saved recording to be used for the purpose of
|
|
/// replay.
|
|
///
|
|
/// The directory will exist in the local file system, be named [basename], and
|
|
/// be a child of the directory identified by [dirname].
|
|
///
|
|
/// If the target directory does not exist, a [ToolExit] will be thrown.
|
|
Directory getReplaySource(String dirname, String basename) {
|
|
final Directory dir = _kLocalFs.directory(_kLocalFs.path.join(dirname, basename));
|
|
if (!dir.existsSync())
|
|
throwToolExit('Invalid replay-from location: $dirname ("$basename" does not exist)');
|
|
return dir;
|
|
}
|
|
|
|
/// 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) => fs.path.normalize(fs.path.absolute(path));
|
|
|
|
/// 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;
|