blob: 482b73f13ebfee12ffbd779d673ac3dcb94e2814 [file] [log] [blame]
// Copyright (c) 2017, 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:async';
import 'package:file/file.dart';
import 'package:file/src/io.dart' as io;
import 'package:meta/meta.dart';
import 'common.dart';
import 'mutable_recording.dart';
import 'recording_directory.dart';
import 'recording_file.dart';
import 'recording_file_system.dart';
import 'recording_link.dart';
import 'recording_proxy_mixin.dart';
/// [FileSystemEntity] implementation that records all invocation activity to
/// its file system's recording.
abstract class RecordingFileSystemEntity<T extends FileSystemEntity>
extends RecordingProxyMixin implements FileSystemEntity {
/// Creates a new `RecordingFileSystemEntity`.
RecordingFileSystemEntity(this.fileSystem, this.delegate) {
methods.addAll(<Symbol, Function>{
#exists: delegate.exists,
#existsSync: delegate.existsSync,
#rename: _rename,
#renameSync: _renameSync,
#resolveSymbolicLinks: delegate.resolveSymbolicLinks,
#resolveSymbolicLinksSync: delegate.resolveSymbolicLinksSync,
#stat: delegate.stat,
#statSync: delegate.statSync,
#delete: _delete,
#deleteSync: delegate.deleteSync,
#watch: delegate.watch,
});
properties.addAll(<Symbol, Function>{
#path: () => delegate.path,
#uri: () => delegate.uri,
#isAbsolute: () => delegate.isAbsolute,
#absolute: _getAbsolute,
#parent: _getParent,
#basename: () => delegate.basename,
#dirname: () => delegate.dirname,
});
}
/// A unique entity id.
final int uid = newUid();
@override
String get identifier => '$runtimeType@$uid';
@override
final RecordingFileSystemImpl fileSystem;
@override
MutableRecording get recording => fileSystem.recording;
@override
Stopwatch get stopwatch => fileSystem.stopwatch;
/// The entity to which this entity delegates its functionality while
/// recording.
@protected
final T delegate;
/// Returns an entity with the same file system and same type as this
/// entity but backed by the specified delegate.
///
/// This base implementation checks to see if the specified delegate is the
/// same as this entity's delegate, and if so, it returns this entity.
/// Otherwise it returns `null`. Subclasses should override this method to
/// instantiate the correct wrapped type only if this super implementation
/// returns `null`.
@protected
@mustCallSuper
T wrap(T delegate) => delegate == this.delegate ? this as T : null;
/// Returns a directory with the same file system as this entity but backed
/// by the specified delegate directory.
@protected
Directory wrapDirectory(io.Directory delegate) =>
new RecordingDirectory(fileSystem, delegate);
/// Returns a file with the same file system as this entity but backed
/// by the specified delegate file.
@protected
File wrapFile(io.File delegate) => new RecordingFile(fileSystem, delegate);
/// Returns a link with the same file system as this entity but backed
/// by the specified delegate link.
@protected
Link wrapLink(io.Link delegate) => new RecordingLink(fileSystem, delegate);
Future<T> _rename(String newPath) => delegate
.rename(newPath)
.then((io.FileSystemEntity entity) => wrap(entity as T));
T _renameSync(String newPath) => wrap(delegate.renameSync(newPath) as T);
Future<T> _delete({bool recursive: false}) => delegate
.delete(recursive: recursive)
.then((io.FileSystemEntity entity) => wrap(entity as T));
T _getAbsolute() => wrap(delegate.absolute as T);
Directory _getParent() => wrapDirectory(delegate.parent);
}