Unverified Commit 63ff7a19 authored by Gary Qian's avatar Gary Qian Committed by GitHub

MigrateConfig and migrate integration testing base (#99092)

parent 1c2c9421
......@@ -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;
}
......
......@@ -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(
'''
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
......@@ -584,11 +625,11 @@ The detected reason was:
if (deprecationBehavior == DeprecationBehavior.ignore) {
BuildEvent('deprecated-v1-android-embedding-ignored', type: 'gradle', flutterUsage: globals.flutterUsage).send();
} else { // DeprecationBehavior.exit
BuildEvent('deprecated-v1-android-embedding-failed', type: 'gradle', flutterUsage: globals.flutterUsage).send();
throwToolExit(
'Build failed due to use of deprecated Android v1 embedding.',
exitCode: 1,
);
BuildEvent('deprecated-v1-android-embedding-failed', type: 'gradle', flutterUsage: globals.flutterUsage).send();
throwToolExit(
'Build failed due to use of deprecated Android v1 embedding.',
exitCode: 1,
);
}
}
......
......@@ -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
......
# 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'));
});
}
// 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'
'''));
});
}
// 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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment