MigrateConfig and migrate integration testing base (#99092)
This commit is contained in:
parent
1c2c942112
commit
63ff7a199b
@ -320,6 +320,7 @@ class CreateCommand extends CreateBase {
|
||||
templateContext,
|
||||
overwrite: overwrite,
|
||||
printStatusWhenWriting: !creatingNewProject,
|
||||
projectType: template,
|
||||
);
|
||||
break;
|
||||
case FlutterProjectType.skeleton:
|
||||
@ -329,6 +330,7 @@ class CreateCommand extends CreateBase {
|
||||
templateContext,
|
||||
overwrite: overwrite,
|
||||
printStatusWhenWriting: !creatingNewProject,
|
||||
generateMetadata: false,
|
||||
);
|
||||
break;
|
||||
case FlutterProjectType.module:
|
||||
@ -353,6 +355,7 @@ class CreateCommand extends CreateBase {
|
||||
templateContext,
|
||||
overwrite: overwrite,
|
||||
printStatusWhenWriting: !creatingNewProject,
|
||||
projectType: template,
|
||||
);
|
||||
break;
|
||||
case FlutterProjectType.ffiPlugin:
|
||||
@ -361,6 +364,7 @@ class CreateCommand extends CreateBase {
|
||||
templateContext,
|
||||
overwrite: overwrite,
|
||||
printStatusWhenWriting: !creatingNewProject,
|
||||
projectType: template,
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -495,6 +499,7 @@ Your $application code is in $relativeAppMain.
|
||||
Map<String, dynamic> templateContext, {
|
||||
bool overwrite = false,
|
||||
bool printStatusWhenWriting = true,
|
||||
FlutterProjectType projectType,
|
||||
}) async {
|
||||
// Plugins only add a platform if it was requested explicitly by the user.
|
||||
if (!argResults.wasParsed('platforms')) {
|
||||
@ -561,6 +566,7 @@ Your $application code is in $relativeAppMain.
|
||||
overwrite: overwrite,
|
||||
pluginExampleApp: true,
|
||||
printStatusWhenWriting: printStatusWhenWriting,
|
||||
projectType: projectType,
|
||||
);
|
||||
return generatedCount;
|
||||
}
|
||||
@ -570,6 +576,7 @@ Your $application code is in $relativeAppMain.
|
||||
Map<String, dynamic> templateContext, {
|
||||
bool overwrite = false,
|
||||
bool printStatusWhenWriting = true,
|
||||
FlutterProjectType projectType,
|
||||
}) async {
|
||||
// Plugins only add a platform if it was requested explicitly by the user.
|
||||
if (!argResults.wasParsed('platforms')) {
|
||||
@ -637,6 +644,7 @@ Your $application code is in $relativeAppMain.
|
||||
overwrite: overwrite,
|
||||
pluginExampleApp: true,
|
||||
printStatusWhenWriting: printStatusWhenWriting,
|
||||
projectType: projectType,
|
||||
);
|
||||
return generatedCount;
|
||||
}
|
||||
|
@ -134,6 +134,13 @@ abstract class CreateBase extends FlutterCommand {
|
||||
'This is only intended to enable testing of the tool itself.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
argParser.addOption(
|
||||
'initial-create-revision',
|
||||
defaultsTo: null,
|
||||
help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
|
||||
'internally and should generally not be used manually.',
|
||||
hide: !verboseHelp,
|
||||
);
|
||||
}
|
||||
|
||||
/// The output directory of the command.
|
||||
@ -488,6 +495,8 @@ abstract class CreateBase extends FlutterCommand {
|
||||
bool overwrite = false,
|
||||
bool pluginExampleApp = false,
|
||||
bool printStatusWhenWriting = true,
|
||||
bool generateMetadata = true,
|
||||
FlutterProjectType projectType,
|
||||
}) async {
|
||||
int generatedCount = 0;
|
||||
generatedCount += await renderMerged(
|
||||
@ -502,6 +511,14 @@ abstract class CreateBase extends FlutterCommand {
|
||||
generatedCount += _injectGradleWrapper(project);
|
||||
}
|
||||
|
||||
final bool androidPlatform = templateContext['android'] as bool ?? false;
|
||||
final bool iosPlatform = templateContext['ios'] as bool ?? false;
|
||||
final bool linuxPlatform = templateContext['linux'] as bool ?? false;
|
||||
final bool macOSPlatform = templateContext['macos'] as bool ?? false;
|
||||
final bool windowsPlatform = templateContext['windows'] as bool ?? false;
|
||||
final bool webPlatform = templateContext['web'] as bool ?? false;
|
||||
final bool winUwpPlatform = templateContext['winuwp'] as bool ?? false;
|
||||
|
||||
if (boolArg('pub')) {
|
||||
final Environment environment = Environment(
|
||||
artifacts: globals.artifacts,
|
||||
@ -534,18 +551,63 @@ abstract class CreateBase extends FlutterCommand {
|
||||
);
|
||||
|
||||
await project.ensureReadyForPlatformSpecificTooling(
|
||||
androidPlatform: templateContext['android'] as bool ?? false,
|
||||
iosPlatform: templateContext['ios'] as bool ?? false,
|
||||
linuxPlatform: templateContext['linux'] as bool ?? false,
|
||||
macOSPlatform: templateContext['macos'] as bool ?? false,
|
||||
windowsPlatform: templateContext['windows'] as bool ?? false,
|
||||
webPlatform: templateContext['web'] as bool ?? false,
|
||||
winUwpPlatform: templateContext['winuwp'] as bool ?? false,
|
||||
androidPlatform: androidPlatform,
|
||||
iosPlatform: iosPlatform,
|
||||
linuxPlatform: linuxPlatform,
|
||||
macOSPlatform: macOSPlatform,
|
||||
windowsPlatform: windowsPlatform,
|
||||
webPlatform: webPlatform,
|
||||
winUwpPlatform: winUwpPlatform,
|
||||
);
|
||||
}
|
||||
if (templateContext['android'] == true) {
|
||||
final List<SupportedPlatform> platformsForMigrateConfig = <SupportedPlatform>[SupportedPlatform.root];
|
||||
if (androidPlatform) {
|
||||
gradle.updateLocalProperties(project: project, requireAndroidSdk: false);
|
||||
platformsForMigrateConfig.add(SupportedPlatform.android);
|
||||
}
|
||||
if (iosPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.ios);
|
||||
}
|
||||
if (linuxPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.linux);
|
||||
}
|
||||
if (macOSPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.macos);
|
||||
}
|
||||
if (webPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.web);
|
||||
}
|
||||
if (windowsPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.windows);
|
||||
}
|
||||
if (winUwpPlatform) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.windowsuwp);
|
||||
}
|
||||
if (templateContext['fuchsia'] == true) {
|
||||
platformsForMigrateConfig.add(SupportedPlatform.fuchsia);
|
||||
}
|
||||
if (generateMetadata) {
|
||||
final File metadataFile = globals.fs
|
||||
.file(globals.fs.path.join(projectDir.absolute.path, '.metadata'));
|
||||
final FlutterProjectMetadata metadata = FlutterProjectMetadata.explicit(
|
||||
file: metadataFile,
|
||||
versionRevision: globals.flutterVersion.frameworkRevision,
|
||||
versionChannel: globals.flutterVersion.channel,
|
||||
projectType: projectType,
|
||||
migrateConfig: MigrateConfig(),
|
||||
logger: globals.logger);
|
||||
metadata.populate(
|
||||
platforms: platformsForMigrateConfig,
|
||||
projectDirectory: directory,
|
||||
create: true,
|
||||
update: false,
|
||||
currentRevision: stringArg('initial-create-revision') ?? globals.flutterVersion.frameworkRevision,
|
||||
createRevision: globals.flutterVersion.frameworkRevision,
|
||||
logger: globals.logger,
|
||||
);
|
||||
metadata.writeFile();
|
||||
}
|
||||
|
||||
return generatedCount;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@ import 'package:yaml/yaml.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/logger.dart';
|
||||
import 'base/utils.dart';
|
||||
import 'project.dart';
|
||||
import 'version.dart';
|
||||
|
||||
enum FlutterProjectType {
|
||||
/// This is the default project with the user-managed host code.
|
||||
@ -27,7 +29,10 @@ enum FlutterProjectType {
|
||||
ffiPlugin,
|
||||
}
|
||||
|
||||
String flutterProjectTypeToString(FlutterProjectType type) {
|
||||
String flutterProjectTypeToString(FlutterProjectType? type) {
|
||||
if (type == null) {
|
||||
return '';
|
||||
}
|
||||
if (type == FlutterProjectType.ffiPlugin) {
|
||||
return 'plugin_ffi';
|
||||
}
|
||||
@ -45,67 +50,286 @@ FlutterProjectType? stringToProjectType(String value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Verifies the expected yaml keys are present in the file.
|
||||
bool _validateMetadataMap(Object? yamlRoot, Map<String, Type> validations, Logger logger) {
|
||||
if (yamlRoot != null && yamlRoot is! YamlMap) {
|
||||
return false;
|
||||
}
|
||||
final YamlMap map = yamlRoot! as YamlMap;
|
||||
bool isValid = true;
|
||||
for (final MapEntry<String, Object> entry in validations.entries) {
|
||||
if (!map.keys.contains(entry.key)) {
|
||||
isValid = false;
|
||||
logger.printTrace('The key `${entry.key}` was not found');
|
||||
break;
|
||||
}
|
||||
if (map[entry.key] != null && (map[entry.key] as Object).runtimeType != entry.value) {
|
||||
isValid = false;
|
||||
logger.printTrace('The value of key `${entry.key}` in .metadata was expected to be ${entry.value} but was ${(map[entry.key] as Object).runtimeType}');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/// A wrapper around the `.metadata` file.
|
||||
class FlutterProjectMetadata {
|
||||
FlutterProjectMetadata(
|
||||
File metadataFile,
|
||||
Logger logger,
|
||||
) : _metadataFile = metadataFile,
|
||||
_logger = logger;
|
||||
/// Creates a MigrateConfig by parsing an existing .migrate_config yaml file.
|
||||
FlutterProjectMetadata(File file, Logger logger) : _metadataFile = file,
|
||||
_logger = logger,
|
||||
migrateConfig = MigrateConfig() {
|
||||
if (!_metadataFile.existsSync()) {
|
||||
_logger.printTrace('No .metadata file found at ${_metadataFile.path}.');
|
||||
// Create a default empty metadata.
|
||||
return;
|
||||
}
|
||||
Object? yamlRoot;
|
||||
try {
|
||||
yamlRoot = loadYaml(_metadataFile.readAsStringSync());
|
||||
} on YamlException {
|
||||
// Handled in _validate below.
|
||||
}
|
||||
if (yamlRoot == null || yamlRoot is! YamlMap) {
|
||||
_logger.printTrace('.metadata file at ${_metadataFile.path} was empty or malformed.');
|
||||
return;
|
||||
}
|
||||
final YamlMap map = yamlRoot;
|
||||
if (_validateMetadataMap(yamlRoot, <String, Type>{'version': YamlMap}, _logger)) {
|
||||
final Object? versionYaml = map['version'];
|
||||
if (_validateMetadataMap(versionYaml, <String, Type>{
|
||||
'revision': String,
|
||||
'channel': String,
|
||||
}, _logger)) {
|
||||
final YamlMap versionYamlMap = versionYaml! as YamlMap;
|
||||
_versionRevision = versionYamlMap['revision'] as String?;
|
||||
_versionChannel = versionYamlMap['channel'] as String?;
|
||||
}
|
||||
}
|
||||
if (_validateMetadataMap(yamlRoot, <String, Type>{'project_type': String}, _logger)) {
|
||||
_projectType = stringToProjectType(map['project_type'] as String);
|
||||
}
|
||||
final Object? migrationYaml = map['migration'];
|
||||
if (migrationYaml != null && migrationYaml is YamlMap) {
|
||||
migrateConfig.parseYaml(map['migration'] as YamlMap, _logger);
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a MigrateConfig by explicitly providing all values.
|
||||
FlutterProjectMetadata.explicit({
|
||||
required File file,
|
||||
required String? versionRevision,
|
||||
required String? versionChannel,
|
||||
required FlutterProjectType? projectType,
|
||||
required this.migrateConfig,
|
||||
required Logger logger,
|
||||
}) : _logger = logger,
|
||||
_versionChannel = versionChannel,
|
||||
_versionRevision = versionRevision,
|
||||
_projectType = projectType,
|
||||
_metadataFile = file;
|
||||
|
||||
/// The name of the config file.
|
||||
static const String kFileName = '.metadata';
|
||||
|
||||
String? _versionRevision;
|
||||
String? get versionRevision => _versionRevision;
|
||||
|
||||
String? _versionChannel;
|
||||
String? get versionChannel => _versionChannel;
|
||||
|
||||
FlutterProjectType? _projectType;
|
||||
FlutterProjectType? get projectType => _projectType;
|
||||
|
||||
/// Metadata and configuration for the migrate command.
|
||||
MigrateConfig migrateConfig;
|
||||
|
||||
final File _metadataFile;
|
||||
final Logger _logger;
|
||||
|
||||
String? get versionChannel => _versionValue('channel');
|
||||
String? get versionRevision => _versionValue('revision');
|
||||
final File _metadataFile;
|
||||
|
||||
FlutterProjectType? get projectType {
|
||||
final dynamic projectTypeYaml = _metadataValue('project_type');
|
||||
if (projectTypeYaml is String) {
|
||||
return stringToProjectType(projectTypeYaml);
|
||||
/// Writes the .migrate_config file in the provided project directory's platform subdirectory.
|
||||
///
|
||||
/// We write the file manually instead of with a template because this
|
||||
/// needs to be able to write the .migrate_config file into legacy apps.
|
||||
void writeFile({File? outputFile}) {
|
||||
outputFile = outputFile ?? _metadataFile;
|
||||
outputFile
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('''
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: $_versionRevision
|
||||
channel: $_versionChannel
|
||||
|
||||
project_type: ${flutterProjectTypeToString(projectType)}
|
||||
${migrateConfig.getOutputFileString()}''',
|
||||
flush: true);
|
||||
}
|
||||
|
||||
void populate({
|
||||
List<SupportedPlatform>? platforms,
|
||||
Directory? projectDirectory,
|
||||
String? currentRevision,
|
||||
String? createRevision,
|
||||
bool create = true,
|
||||
bool update = true,
|
||||
required Logger logger,
|
||||
}) {
|
||||
migrateConfig.populate(
|
||||
platforms: platforms,
|
||||
projectDirectory: projectDirectory,
|
||||
currentRevision: currentRevision,
|
||||
createRevision: createRevision,
|
||||
create: create,
|
||||
update: update,
|
||||
logger: logger,
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds the fallback revision to use when no base revision is found in the migrate config.
|
||||
String getFallbackBaseRevision(Logger logger, FlutterVersion flutterVersion) {
|
||||
// Use the .metadata file if it exists.
|
||||
if (versionRevision != null) {
|
||||
return versionRevision!;
|
||||
}
|
||||
return flutterVersion.frameworkRevision;
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the migrate command metadata section of a .metadata file.
|
||||
///
|
||||
/// This file tracks the flutter sdk git hashes of the last successful migration ('base') and
|
||||
/// the version the project was created with.
|
||||
///
|
||||
/// Each platform tracks a different set of revisions because flutter create can be
|
||||
/// used to add support for new platforms, so the base and create revision may not always be the same.
|
||||
class MigrateConfig {
|
||||
MigrateConfig({
|
||||
Map<SupportedPlatform, MigratePlatformConfig>? platformConfigs,
|
||||
this.unmanagedFiles = _kDefaultUnmanagedFiles
|
||||
}) : platformConfigs = platformConfigs ?? <SupportedPlatform, MigratePlatformConfig>{};
|
||||
|
||||
/// A mapping of the files that are unmanaged by defult for each platform.
|
||||
static const List<String> _kDefaultUnmanagedFiles = <String>[
|
||||
'lib/main.dart',
|
||||
'ios/Runner.xcodeproj/project.pbxproj',
|
||||
];
|
||||
|
||||
/// The metadata for each platform supported by the project.
|
||||
final Map<SupportedPlatform, MigratePlatformConfig> platformConfigs;
|
||||
|
||||
/// A list of paths relative to this file the migrate tool should ignore.
|
||||
///
|
||||
/// These files are typically user-owned files that should not be changed.
|
||||
List<String> unmanagedFiles;
|
||||
|
||||
bool get isEmpty => platformConfigs.isEmpty && (unmanagedFiles.isEmpty || unmanagedFiles == _kDefaultUnmanagedFiles);
|
||||
|
||||
/// Parses the project for all supported platforms and populates the [MigrateConfig]
|
||||
/// to reflect the project.
|
||||
void populate({
|
||||
List<SupportedPlatform>? platforms,
|
||||
Directory? projectDirectory,
|
||||
String? currentRevision,
|
||||
String? createRevision,
|
||||
bool create = true,
|
||||
bool update = true,
|
||||
required Logger logger,
|
||||
}) {
|
||||
final FlutterProject flutterProject = projectDirectory == null ? FlutterProject.current() : FlutterProject.fromDirectory(projectDirectory);
|
||||
platforms ??= flutterProject.getSupportedPlatforms(includeRoot: true);
|
||||
|
||||
for (final SupportedPlatform platform in platforms) {
|
||||
if (platformConfigs.containsKey(platform)) {
|
||||
if (update) {
|
||||
platformConfigs[platform]!.baseRevision = currentRevision;
|
||||
}
|
||||
} else {
|
||||
_logger.printTrace('.metadata project_type version is malformed.');
|
||||
return null;
|
||||
if (create) {
|
||||
platformConfigs[platform] = MigratePlatformConfig(createRevision: createRevision, baseRevision: currentRevision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YamlMap? _versionYaml;
|
||||
String? _versionValue(String key) {
|
||||
if (_versionYaml == null) {
|
||||
final dynamic versionYaml = _metadataValue('version');
|
||||
if (versionYaml is YamlMap) {
|
||||
_versionYaml = versionYaml;
|
||||
/// Returns the string that should be written to the .metadata file.
|
||||
String getOutputFileString() {
|
||||
String unmanagedFilesString = '';
|
||||
for (final String path in unmanagedFiles) {
|
||||
unmanagedFilesString += "\n - '$path'";
|
||||
}
|
||||
|
||||
String platformsString = '';
|
||||
for (final MapEntry<SupportedPlatform, MigratePlatformConfig> entry in platformConfigs.entries) {
|
||||
platformsString += '\n - platform: ${entry.key.toString().split('.').last}\n create_revision: ${entry.value.createRevision == null ? 'null' : "${entry.value.createRevision}"}\n base_revision: ${entry.value.baseRevision == null ? 'null' : "${entry.value.baseRevision}"}';
|
||||
}
|
||||
|
||||
return isEmpty ? '' : '''
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:$platformsString
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:$unmanagedFilesString
|
||||
''';
|
||||
}
|
||||
|
||||
/// Parses and validates the `migration` section of the .metadata file.
|
||||
void parseYaml(YamlMap map, Logger logger) {
|
||||
final Object? platformsYaml = map['platforms'];
|
||||
if (_validateMetadataMap(map, <String, Type>{'platforms': YamlList}, logger)) {
|
||||
if (platformsYaml is YamlList && platformsYaml.isNotEmpty) {
|
||||
for (final Object? platform in platformsYaml) {
|
||||
if (_validateMetadataMap(platform, <String, Type>{
|
||||
'platform': String,
|
||||
'create_revision': String,
|
||||
'base_revision': String,
|
||||
}, logger)) {
|
||||
final YamlMap platformYamlMap = platform! as YamlMap;
|
||||
final SupportedPlatform platformString = SupportedPlatform.values.firstWhere(
|
||||
(SupportedPlatform val) => val.toString() == 'SupportedPlatform.${platformYamlMap['platform'] as String}'
|
||||
);
|
||||
platformConfigs[platformString] = MigratePlatformConfig(
|
||||
createRevision: platformYamlMap['create_revision'] as String?,
|
||||
baseRevision: platformYamlMap['base_revision'] as String?,
|
||||
);
|
||||
} else {
|
||||
_logger.printTrace('.metadata version is malformed.');
|
||||
return null;
|
||||
// malformed platform entry
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (_versionYaml != null && _versionYaml!.containsKey(key) && _versionYaml![key] is String) {
|
||||
return _versionYaml![key] as String;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
YamlMap? _metadataYaml;
|
||||
dynamic _metadataValue(String key) {
|
||||
if (_metadataYaml == null) {
|
||||
if (!_metadataFile.existsSync()) {
|
||||
return null;
|
||||
if (_validateMetadataMap(map, <String, Type>{'unmanaged_files': YamlList}, logger)) {
|
||||
final Object? unmanagedFilesYaml = map['unmanaged_files'];
|
||||
if (unmanagedFilesYaml is YamlList && unmanagedFilesYaml.isNotEmpty) {
|
||||
unmanagedFiles = List<String>.from(unmanagedFilesYaml.value.cast<String>());
|
||||
}
|
||||
dynamic metadataYaml;
|
||||
try {
|
||||
metadataYaml = loadYaml(_metadataFile.readAsStringSync());
|
||||
} on YamlException {
|
||||
// Handled in return below.
|
||||
}
|
||||
if (metadataYaml is YamlMap) {
|
||||
_metadataYaml = metadataYaml;
|
||||
} else {
|
||||
_logger.printTrace('.metadata is malformed.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return _metadataYaml![key];
|
||||
}
|
||||
/// Holds the revisions for a single platform for use by the flutter migrate command.
|
||||
class MigratePlatformConfig {
|
||||
MigratePlatformConfig({this.createRevision, this.baseRevision});
|
||||
|
||||
/// The Flutter SDK revision this platform was created by.
|
||||
///
|
||||
/// Null if the initial create git revision is unknown.
|
||||
final String? createRevision;
|
||||
|
||||
/// The Flutter SDK revision this platform was last migrated by.
|
||||
///
|
||||
/// Null if the project was never migrated or the revision is unknown.
|
||||
String? baseRevision;
|
||||
}
|
||||
|
@ -27,6 +27,19 @@ import 'xcode_project.dart';
|
||||
export 'cmake_project.dart';
|
||||
export 'xcode_project.dart';
|
||||
|
||||
/// Emum for each officially supported platform.
|
||||
enum SupportedPlatform {
|
||||
android,
|
||||
ios,
|
||||
linux,
|
||||
macos,
|
||||
web,
|
||||
windows,
|
||||
windowsuwp,
|
||||
fuchsia,
|
||||
root, // Special platform to represent the root project directory
|
||||
}
|
||||
|
||||
class FlutterProjectFactory {
|
||||
FlutterProjectFactory({
|
||||
required Logger logger,
|
||||
@ -244,6 +257,36 @@ class FlutterProject {
|
||||
/// True if this project has an example application.
|
||||
bool get hasExampleApp => _exampleDirectory(directory).existsSync();
|
||||
|
||||
/// Returns a list of platform names that are supported by the project.
|
||||
List<SupportedPlatform> getSupportedPlatforms({bool includeRoot = false}) {
|
||||
final List<SupportedPlatform> platforms = includeRoot ? <SupportedPlatform>[SupportedPlatform.root] : <SupportedPlatform>[];
|
||||
if (android.existsSync()) {
|
||||
platforms.add(SupportedPlatform.android);
|
||||
}
|
||||
if (ios.exists) {
|
||||
platforms.add(SupportedPlatform.ios);
|
||||
}
|
||||
if (web.existsSync()) {
|
||||
platforms.add(SupportedPlatform.web);
|
||||
}
|
||||
if (macos.existsSync()) {
|
||||
platforms.add(SupportedPlatform.macos);
|
||||
}
|
||||
if (linux.existsSync()) {
|
||||
platforms.add(SupportedPlatform.linux);
|
||||
}
|
||||
if (windows.existsSync()) {
|
||||
platforms.add(SupportedPlatform.windows);
|
||||
}
|
||||
if (windowsUwp.existsSync()) {
|
||||
platforms.add(SupportedPlatform.windowsuwp);
|
||||
}
|
||||
if (fuchsia.existsSync()) {
|
||||
platforms.add(SupportedPlatform.fuchsia);
|
||||
}
|
||||
return platforms;
|
||||
}
|
||||
|
||||
/// The directory that will contain the example if an example exists.
|
||||
static Directory _exampleDirectory(Directory directory) => directory.childDirectory('example');
|
||||
|
||||
@ -555,12 +598,10 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
if (deprecationBehavior == DeprecationBehavior.none) {
|
||||
return;
|
||||
}
|
||||
|
||||
final AndroidEmbeddingVersionResult result = computeEmbeddingVersion();
|
||||
if (result.version != AndroidEmbeddingVersion.v1) {
|
||||
return;
|
||||
}
|
||||
|
||||
globals.printStatus(
|
||||
'''
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
@ -134,6 +134,12 @@ class IosProject extends XcodeBasedProject {
|
||||
|
||||
Directory get symlinks => _flutterLibRoot.childDirectory('.symlinks');
|
||||
|
||||
/// True, if the app project is using swift.
|
||||
bool get isSwift {
|
||||
final File appDelegateSwift = _editableDirectory.childDirectory('Runner').childFile('AppDelegate.swift');
|
||||
return appDelegateSwift.existsSync();
|
||||
}
|
||||
|
||||
/// Do all plugins support arm64 simulators to run natively on an ARM Mac?
|
||||
Future<bool> pluginsSupportArmSimulator() async {
|
||||
final Directory podXcodeProject = hostAppRoot
|
||||
|
@ -8,6 +8,7 @@
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
@ -1,10 +0,0 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: {{flutterRevision}}
|
||||
channel: {{flutterChannel}}
|
||||
|
||||
project_type: app
|
@ -9,6 +9,8 @@
|
||||
.sconsign.dblite
|
||||
.svn/
|
||||
|
||||
migrate_working_dir/
|
||||
|
||||
*.swp
|
||||
profile
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
@ -8,6 +8,7 @@
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
@ -88,19 +88,19 @@ void main() {
|
||||
await runner.run(<String>['create', '--no-pub', '--template=module', 'testy']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'module');
|
||||
|
||||
await runner.run(<String>['create', '--no-pub', '--template=app', 'testy']);
|
||||
await runner.run(<String>['create', '--no-pub', '--template=app', 'testy1']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'app');
|
||||
|
||||
await runner.run(<String>['create', '--no-pub', '--template=skeleton', 'testy']);
|
||||
await runner.run(<String>['create', '--no-pub', '--template=skeleton', 'testy2']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'skeleton');
|
||||
|
||||
await runner.run(<String>['create', '--no-pub', '--template=package', 'testy']);
|
||||
await runner.run(<String>['create', '--no-pub', '--template=package', 'testy3']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'package');
|
||||
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin', 'testy']);
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin', 'testy4']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'plugin');
|
||||
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin_ffi', 'testy']);
|
||||
await runner.run(<String>['create', '--no-pub', '--template=plugin_ffi', 'testy5']);
|
||||
expect((await command.usageValues).commandCreateProjectType, 'plugin_ffi');
|
||||
}));
|
||||
|
||||
|
@ -6,6 +6,7 @@ import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/flutter_project_metadata.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
|
||||
@ -26,8 +27,7 @@ void main() {
|
||||
expect(projectMetadata.versionChannel, isNull);
|
||||
expect(projectMetadata.versionRevision, isNull);
|
||||
|
||||
expect(logger.traceText, contains('.metadata project_type version is malformed.'));
|
||||
expect(logger.traceText, contains('.metadata version is malformed.'));
|
||||
expect(logger.traceText, contains('No .metadata file found at .metadata'));
|
||||
});
|
||||
|
||||
testWithoutContext('project metadata fields are empty when file is empty', () {
|
||||
@ -37,8 +37,7 @@ void main() {
|
||||
expect(projectMetadata.versionChannel, isNull);
|
||||
expect(projectMetadata.versionRevision, isNull);
|
||||
|
||||
expect(logger.traceText, contains('.metadata project_type version is malformed.'));
|
||||
expect(logger.traceText, contains('.metadata version is malformed.'));
|
||||
expect(logger.traceText, contains('.metadata file at .metadata was empty or malformed.'));
|
||||
});
|
||||
|
||||
testWithoutContext('project metadata fields are empty when file is not valid yaml', () {
|
||||
@ -48,8 +47,7 @@ void main() {
|
||||
expect(projectMetadata.versionChannel, isNull);
|
||||
expect(projectMetadata.versionRevision, isNull);
|
||||
|
||||
expect(logger.traceText, contains('.metadata project_type version is malformed.'));
|
||||
expect(logger.traceText, contains('.metadata version is malformed.'));
|
||||
expect(logger.traceText, contains('.metadata file at .metadata was empty or malformed.'));
|
||||
});
|
||||
|
||||
testWithoutContext('projectType is populated when version is malformed', () {
|
||||
@ -64,7 +62,7 @@ project_type: plugin
|
||||
expect(projectMetadata.versionChannel, isNull);
|
||||
expect(projectMetadata.versionRevision, isNull);
|
||||
|
||||
expect(logger.traceText, contains('.metadata version is malformed.'));
|
||||
expect(logger.traceText, contains('The value of key `version` in .metadata was expected to be YamlMap but was String'));
|
||||
});
|
||||
|
||||
testWithoutContext('version is populated when projectType is malformed', () {
|
||||
@ -81,6 +79,94 @@ project_type: {}
|
||||
expect(projectMetadata.versionChannel, 'stable');
|
||||
expect(projectMetadata.versionRevision, 'b59b226a49391949247e3d6122e34bb001049ae4');
|
||||
|
||||
expect(logger.traceText, contains('.metadata project_type version is malformed.'));
|
||||
expect(logger.traceText, contains('The value of key `project_type` in .metadata was expected to be String but was YamlMap'));
|
||||
});
|
||||
|
||||
testWithoutContext('migrate config is populated when version is malformed', () {
|
||||
metadataFile
|
||||
..createSync()
|
||||
..writeAsStringSync('''
|
||||
version: STRING INSTEAD OF MAP
|
||||
project_type: {}
|
||||
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: abcdefg
|
||||
base_revision: baserevision
|
||||
|
||||
unmanaged_files:
|
||||
- 'file1'
|
||||
''');
|
||||
final FlutterProjectMetadata projectMetadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
expect(projectMetadata.projectType, isNull);
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.createRevision, 'abcdefg');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.baseRevision, 'baserevision');
|
||||
expect(projectMetadata.migrateConfig.unmanagedFiles[0], 'file1');
|
||||
|
||||
expect(logger.traceText, contains('The value of key `version` in .metadata was expected to be YamlMap but was String'));
|
||||
expect(logger.traceText, contains('The value of key `project_type` in .metadata was expected to be String but was YamlMap'));
|
||||
});
|
||||
|
||||
testWithoutContext('migrate config is populated when unmanaged_files is malformed', () {
|
||||
metadataFile
|
||||
..createSync()
|
||||
..writeAsStringSync('''
|
||||
version:
|
||||
revision: b59b226a49391949247e3d6122e34bb001049ae4
|
||||
channel: stable
|
||||
project_type: app
|
||||
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: abcdefg
|
||||
base_revision: baserevision
|
||||
|
||||
unmanaged_files: {}
|
||||
''');
|
||||
final FlutterProjectMetadata projectMetadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
expect(projectMetadata.projectType, FlutterProjectType.app);
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.createRevision, 'abcdefg');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.baseRevision, 'baserevision');
|
||||
// Tool uses default unamanged files list when malformed.
|
||||
expect(projectMetadata.migrateConfig.unmanagedFiles[0], 'lib/main.dart');
|
||||
|
||||
expect(logger.traceText, contains('The value of key `unmanaged_files` in .metadata was expected to be YamlList but was YamlMap'));
|
||||
});
|
||||
|
||||
testWithoutContext('platforms is populated with a malformed entry', () {
|
||||
metadataFile
|
||||
..createSync()
|
||||
..writeAsStringSync('''
|
||||
version:
|
||||
revision: b59b226a49391949247e3d6122e34bb001049ae4
|
||||
channel: stable
|
||||
project_type: app
|
||||
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: abcdefg
|
||||
base_revision: baserevision
|
||||
- platform: android
|
||||
base_revision: baserevision
|
||||
- platform: ios
|
||||
create_revision: abcdefg
|
||||
base_revision: baserevision
|
||||
|
||||
unmanaged_files:
|
||||
- 'file1'
|
||||
''');
|
||||
final FlutterProjectMetadata projectMetadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
expect(projectMetadata.projectType, FlutterProjectType.app);
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.createRevision, 'abcdefg');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.root]?.baseRevision, 'baserevision');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.ios]?.createRevision, 'abcdefg');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs[SupportedPlatform.ios]?.baseRevision, 'baserevision');
|
||||
expect(projectMetadata.migrateConfig.platformConfigs.containsKey(SupportedPlatform.android), false);
|
||||
expect(projectMetadata.migrateConfig.unmanagedFiles[0], 'file1');
|
||||
|
||||
expect(logger.traceText, contains('The key `create_revision` was not found'));
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,231 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/flutter_project_metadata.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
import 'test_data/migrate_project.dart';
|
||||
import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
|
||||
void main() {
|
||||
Directory tempDir;
|
||||
FlutterRunTestDriver flutter;
|
||||
Logger logger;
|
||||
|
||||
setUp(() async {
|
||||
tempDir = createResolvedTempDirectorySync('run_test.');
|
||||
flutter = FlutterRunTestDriver(tempDir);
|
||||
logger = BufferLogger.test();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await flutter.stop();
|
||||
tryToDelete(tempDir);
|
||||
});
|
||||
|
||||
testWithoutContext('parse simple config file', () async {
|
||||
final File metadataFile = tempDir.childFile('.metadata');
|
||||
metadataFile.createSync(recursive: true);
|
||||
metadataFile.writeAsStringSync('''
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: fj19vkla9vnlka9vni3n808v3nch8cd
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: fj19vkla9vnlka9vni3n808v3nch8cd
|
||||
base_revision: 93kf9v3njfa90vnidfjvn39nvi3vnie
|
||||
- platform: android
|
||||
create_revision: abfj19vkla9vnlka9vni3n808v3nch8cd
|
||||
base_revision: ab93kf9v3njfa90vnidfjvn39nvi3vnie
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- lib/main.dart
|
||||
- ios/Runner.xcodeproj/project.pbxproj
|
||||
- lib/file1/etc.dart
|
||||
- android/my_file.java
|
||||
''', flush: true);
|
||||
FlutterProjectMetadata metadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.root].createRevision, equals('fj19vkla9vnlka9vni3n808v3nch8cd'));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.root].baseRevision, equals('93kf9v3njfa90vnidfjvn39nvi3vnie'));
|
||||
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.android].createRevision, equals('abfj19vkla9vnlka9vni3n808v3nch8cd'));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.android].baseRevision, equals('ab93kf9v3njfa90vnidfjvn39nvi3vnie'));
|
||||
|
||||
expect(metadata.migrateConfig.unmanagedFiles[0], equals('lib/main.dart'));
|
||||
expect(metadata.migrateConfig.unmanagedFiles[1], equals('ios/Runner.xcodeproj/project.pbxproj'));
|
||||
expect(metadata.migrateConfig.unmanagedFiles[2], equals('lib/file1/etc.dart'));
|
||||
expect(metadata.migrateConfig.unmanagedFiles[3], equals('android/my_file.java'));
|
||||
|
||||
metadataFile.writeAsStringSync('''
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: fj19vkla9vnlka9vni3n808v3nch8cd
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
''', flush: true);
|
||||
|
||||
metadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
|
||||
expect(metadata.migrateConfig.isEmpty, equals(true));
|
||||
expect(metadata.versionRevision, equals('fj19vkla9vnlka9vni3n808v3nch8cd'));
|
||||
expect(metadata.versionChannel, equals('stable'));
|
||||
});
|
||||
|
||||
testUsingContext('write simple config file', () async {
|
||||
const String testCreateRevision = 'testmc9skl32nlnf23lnakcs9njr3';
|
||||
const String testBaseRevision = 'testanas9anlnq9ba7bjhavan3kma';
|
||||
MigrateConfig config = MigrateConfig(
|
||||
platformConfigs: <SupportedPlatform, MigratePlatformConfig>{
|
||||
SupportedPlatform.android: MigratePlatformConfig(createRevision: testCreateRevision, baseRevision: testBaseRevision),
|
||||
SupportedPlatform.ios: MigratePlatformConfig(createRevision: testCreateRevision, baseRevision: testBaseRevision),
|
||||
SupportedPlatform.root: MigratePlatformConfig(createRevision: testCreateRevision, baseRevision: testBaseRevision),
|
||||
SupportedPlatform.windows: MigratePlatformConfig(createRevision: testCreateRevision, baseRevision: testBaseRevision),
|
||||
},
|
||||
unmanagedFiles: <String>[
|
||||
'lib/main.dart',
|
||||
'ios/Runner.xcodeproj/project.pbxproj',
|
||||
'lib/file1/etc.dart',
|
||||
],
|
||||
);
|
||||
String outputString = config.getOutputFileString();
|
||||
expect(outputString, equals('''
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: android
|
||||
create_revision: $testCreateRevision
|
||||
base_revision: $testBaseRevision
|
||||
- platform: ios
|
||||
create_revision: $testCreateRevision
|
||||
base_revision: $testBaseRevision
|
||||
- platform: root
|
||||
create_revision: $testCreateRevision
|
||||
base_revision: $testBaseRevision
|
||||
- platform: windows
|
||||
create_revision: $testCreateRevision
|
||||
base_revision: $testBaseRevision
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
- 'lib/file1/etc.dart'
|
||||
'''));
|
||||
|
||||
config = MigrateConfig();
|
||||
outputString = config.getOutputFileString();
|
||||
expect(outputString, equals(''));
|
||||
});
|
||||
|
||||
testUsingContext('populate migrate config', () async {
|
||||
// Flutter Stable 1.22.6 hash: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
|
||||
final MigrateProject project = MigrateProject('version:1.22.6_stable');
|
||||
await project.setUpIn(tempDir);
|
||||
|
||||
final File metadataFile = tempDir.childFile('.metadata');
|
||||
|
||||
const String currentRevision = 'test_base_revision';
|
||||
const String createRevision = 'test_create_revision';
|
||||
|
||||
final FlutterProjectMetadata metadata = FlutterProjectMetadata(metadataFile, logger);
|
||||
metadata.migrateConfig.populate(
|
||||
projectDirectory: tempDir,
|
||||
currentRevision: currentRevision,
|
||||
createRevision: createRevision,
|
||||
create: true,
|
||||
update: true,
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
expect(metadata.migrateConfig.platformConfigs.length, equals(3));
|
||||
|
||||
final List<SupportedPlatform> keyList = List<SupportedPlatform>.from(metadata.migrateConfig.platformConfigs.keys);
|
||||
|
||||
expect(keyList[0], equals(SupportedPlatform.root));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.root].baseRevision, equals(currentRevision));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.root].createRevision, equals(createRevision));
|
||||
|
||||
expect(keyList[1], equals(SupportedPlatform.android));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.android].baseRevision, equals(currentRevision));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.android].createRevision, equals(createRevision));
|
||||
|
||||
expect(keyList[2], equals(SupportedPlatform.ios));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.ios].baseRevision, equals(currentRevision));
|
||||
expect(metadata.migrateConfig.platformConfigs[SupportedPlatform.ios].createRevision, equals(createRevision));
|
||||
|
||||
final File metadataFileOutput = tempDir.childFile('.metadata_output');
|
||||
metadata.writeFile(outputFile: metadataFileOutput);
|
||||
expect(metadataFileOutput.readAsStringSync(), equals('''
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
|
||||
channel: unknown
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: $createRevision
|
||||
base_revision: $currentRevision
|
||||
- platform: android
|
||||
create_revision: $createRevision
|
||||
base_revision: $currentRevision
|
||||
- platform: ios
|
||||
create_revision: $createRevision
|
||||
base_revision: $currentRevision
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
'''));
|
||||
});
|
||||
}
|
@ -0,0 +1 @@
|
||||
flutter/test/full_app_fixtures/vanilla version:1.22.6_stable
|
@ -0,0 +1,237 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@Timeout(Duration(seconds: 600))
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:file/file.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../test_utils.dart';
|
||||
import 'project.dart';
|
||||
|
||||
class MigrateProject extends Project {
|
||||
MigrateProject(this.version, {this.vanilla = true});
|
||||
|
||||
@override
|
||||
Future<void> setUpIn(Directory dir, {
|
||||
bool useDeferredLoading = false,
|
||||
bool useSyntheticPackage = false,
|
||||
}) async {
|
||||
this.dir = dir;
|
||||
_appPath = dir.path;
|
||||
if (androidLocalProperties != null) {
|
||||
writeFile(fileSystem.path.join(dir.path, 'android', 'local.properties'), androidLocalProperties);
|
||||
}
|
||||
final Directory tempDir = createResolvedTempDirectorySync('cipd_dest.');
|
||||
final Directory depotToolsDir = createResolvedTempDirectorySync('depot_tools.');
|
||||
|
||||
await processManager.run(<String>[
|
||||
'git',
|
||||
'clone',
|
||||
'https://chromium.googlesource.com/chromium/tools/depot_tools',
|
||||
depotToolsDir.path,
|
||||
], workingDirectory: dir.path);
|
||||
|
||||
final File cipdFile = depotToolsDir.childFile(Platform.isWindows ? 'cipd.bat' : 'cipd');
|
||||
await processManager.run(<String>[
|
||||
cipdFile.path,
|
||||
'init',
|
||||
tempDir.path,
|
||||
'-force',
|
||||
], workingDirectory: dir.path);
|
||||
|
||||
await processManager.run(<String>[
|
||||
cipdFile.path,
|
||||
'install',
|
||||
'flutter/test/full_app_fixtures/vanilla',
|
||||
version,
|
||||
'-root',
|
||||
tempDir.path,
|
||||
], workingDirectory: dir.path);
|
||||
|
||||
if (Platform.isWindows) {
|
||||
await processManager.run(<String>[
|
||||
'robocopy',
|
||||
tempDir.path,
|
||||
dir.path,
|
||||
'*',
|
||||
'/E',
|
||||
'/mov',
|
||||
]);
|
||||
// Add full access permissions to Users
|
||||
await processManager.run(<String>[
|
||||
'icacls',
|
||||
tempDir.path,
|
||||
'/q',
|
||||
'/c',
|
||||
'/t',
|
||||
'/grant',
|
||||
'Users:F',
|
||||
]);
|
||||
} else {
|
||||
// This cp command changes the symlinks to real files so the tool can edit them.
|
||||
await processManager.run(<String>[
|
||||
'cp',
|
||||
'-R',
|
||||
'-L',
|
||||
'-f',
|
||||
'${tempDir.path}/.',
|
||||
dir.path,
|
||||
]);
|
||||
|
||||
await processManager.run(<String>[
|
||||
'rm',
|
||||
'-rf',
|
||||
'.cipd',
|
||||
], workingDirectory: dir.path);
|
||||
|
||||
final List<FileSystemEntity> allFiles = dir.listSync(recursive: true);
|
||||
for (final FileSystemEntity file in allFiles) {
|
||||
if (file is! File) {
|
||||
continue;
|
||||
}
|
||||
await processManager.run(<String>[
|
||||
'chmod',
|
||||
'+w',
|
||||
file.path,
|
||||
], workingDirectory: dir.path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vanilla) {
|
||||
writeFile(fileSystem.path.join(dir.path, 'lib', 'main.dart'), libMain);
|
||||
writeFile(fileSystem.path.join(dir.path, 'lib', 'other.dart'), libOther);
|
||||
writeFile(fileSystem.path.join(dir.path, 'pubspec.yaml'), pubspecCustom);
|
||||
}
|
||||
tryToDelete(tempDir);
|
||||
tryToDelete(depotToolsDir);
|
||||
}
|
||||
|
||||
final String version;
|
||||
final bool vanilla;
|
||||
late String _appPath;
|
||||
|
||||
// Maintain the same pubspec as the configured app.
|
||||
@override
|
||||
String get pubspec => fileSystem.file(fileSystem.path.join(_appPath, 'pubspec.yaml')).readAsStringSync();
|
||||
|
||||
String get androidLocalProperties => '''
|
||||
flutter.sdk=${getFlutterRoot()}
|
||||
''';
|
||||
|
||||
String get libMain => '''
|
||||
import 'package:flutter/material.dart';
|
||||
import 'other.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
),
|
||||
home: OtherWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
''';
|
||||
|
||||
String get libOther => '''
|
||||
class OtherWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(width: 100, height: 100);
|
||||
}
|
||||
}
|
||||
|
||||
''';
|
||||
|
||||
String get pubspecCustom => '''
|
||||
name: vanilla_app_1_22_6_stable
|
||||
description: This is a modified description from the default.
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.6.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- images/a_dot_burr.jpeg
|
||||
- images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
|
||||
''';
|
||||
}
|
@ -33,7 +33,7 @@ Directory createResolvedTempDirectorySync(String prefix) {
|
||||
void writeFile(String path, String content, {bool writeFutureModifiedDate = false}) {
|
||||
final File file = fileSystem.file(path)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(content);
|
||||
..writeAsStringSync(content, flush: true);
|
||||
// Some integration tests on Windows to not see this file as being modified
|
||||
// recently enough for the hot reload to pick this change up unless the
|
||||
// modified time is written in the future.
|
||||
|
Loading…
x
Reference in New Issue
Block a user