flutter build ios-framework generate Flutter.podspec (#47556)
This commit is contained in:
@@ -235,6 +235,34 @@ class Cache {
|
||||
}
|
||||
String _engineRevision;
|
||||
|
||||
String get storageBaseUrl {
|
||||
final String overrideUrl = platform.environment['FLUTTER_STORAGE_BASE_URL'];
|
||||
if (overrideUrl == null) {
|
||||
return 'https://storage.googleapis.com';
|
||||
}
|
||||
// verify that this is a valid URI.
|
||||
try {
|
||||
Uri.parse(overrideUrl);
|
||||
} on FormatException catch (err) {
|
||||
throwToolExit('"FLUTTER_STORAGE_BASE_URL" contains an invalid URI:\n$err');
|
||||
}
|
||||
_maybeWarnAboutStorageOverride(overrideUrl);
|
||||
return overrideUrl;
|
||||
}
|
||||
|
||||
bool _hasWarnedAboutStorageOverride = false;
|
||||
|
||||
void _maybeWarnAboutStorageOverride(String overrideUrl) {
|
||||
if (_hasWarnedAboutStorageOverride) {
|
||||
return;
|
||||
}
|
||||
logger.printStatus(
|
||||
'Flutter assets will be downloaded from $overrideUrl. Make sure you trust this source!',
|
||||
emphasis: true,
|
||||
);
|
||||
_hasWarnedAboutStorageOverride = true;
|
||||
}
|
||||
|
||||
static Cache get instance => context.get<Cache>();
|
||||
|
||||
/// Return the top-level directory in the cache; this is `bin/cache`.
|
||||
@@ -262,6 +290,9 @@ class Cache {
|
||||
/// Return the top-level mutable directory in the cache; this is `bin/cache/artifacts`.
|
||||
Directory getCacheArtifacts() => getCacheDir('artifacts');
|
||||
|
||||
/// Location of LICENSE file.
|
||||
File getLicenseFile() => fs.file(fs.path.join(flutterRoot, 'LICENSE'));
|
||||
|
||||
/// Get a named directory from with the cache's artifact directory; for example,
|
||||
/// `material_fonts` would return `bin/cache/artifacts/material_fonts`.
|
||||
Directory getArtifactDirectory(String name) {
|
||||
@@ -492,23 +523,7 @@ abstract class CachedArtifact extends ArtifactSet {
|
||||
/// Template method to perform artifact update.
|
||||
Future<void> updateInner();
|
||||
|
||||
@visibleForTesting
|
||||
String get storageBaseUrl {
|
||||
final String overrideUrl = platform.environment['FLUTTER_STORAGE_BASE_URL'];
|
||||
if (overrideUrl == null) {
|
||||
return 'https://storage.googleapis.com';
|
||||
}
|
||||
// verify that this is a valid URI.
|
||||
try {
|
||||
Uri.parse(overrideUrl);
|
||||
} on FormatException catch (err) {
|
||||
throwToolExit('"FLUTTER_STORAGE_BASE_URL" contains an invalid URI:\n$err');
|
||||
}
|
||||
_maybeWarnAboutStorageOverride(overrideUrl);
|
||||
return overrideUrl;
|
||||
}
|
||||
|
||||
Uri _toStorageUri(String path) => Uri.parse('$storageBaseUrl/$path');
|
||||
Uri _toStorageUri(String path) => Uri.parse('${cache.storageBaseUrl}/$path');
|
||||
|
||||
/// Download an archive from the given [url] and unzip it to [location].
|
||||
Future<void> _downloadArchive(String message, Uri url, Directory location, bool verifier(File f), void extractor(File f, Directory d)) {
|
||||
@@ -549,19 +564,6 @@ abstract class CachedArtifact extends ArtifactSet {
|
||||
}
|
||||
}
|
||||
|
||||
bool _hasWarnedAboutStorageOverride = false;
|
||||
|
||||
void _maybeWarnAboutStorageOverride(String overrideUrl) {
|
||||
if (_hasWarnedAboutStorageOverride) {
|
||||
return;
|
||||
}
|
||||
logger.printStatus(
|
||||
'Flutter assets will be downloaded from $overrideUrl. Make sure you trust this source!',
|
||||
emphasis: true,
|
||||
);
|
||||
_hasWarnedAboutStorageOverride = true;
|
||||
}
|
||||
|
||||
/// A cached artifact containing fonts used for Material Design.
|
||||
class MaterialFonts extends CachedArtifact {
|
||||
MaterialFonts(Cache cache) : super(
|
||||
@@ -604,7 +606,7 @@ class FlutterWebSdk extends CachedArtifact {
|
||||
} else if (platform.isWindows) {
|
||||
platformName += 'windows-x64';
|
||||
}
|
||||
final Uri url = Uri.parse('$storageBaseUrl/flutter_infra/flutter/$version/$platformName.zip');
|
||||
final Uri url = Uri.parse('${cache.storageBaseUrl}/flutter_infra/flutter/$version/$platformName.zip');
|
||||
await _downloadZipArchive('Downloading Web SDK...', url, location);
|
||||
// This is a temporary work-around for not being able to safely download into a shared directory.
|
||||
for (FileSystemEntity entity in location.listSync(recursive: true)) {
|
||||
@@ -669,7 +671,7 @@ abstract class EngineCachedArtifact extends CachedArtifact {
|
||||
|
||||
@override
|
||||
Future<void> updateInner() async {
|
||||
final String url = '$storageBaseUrl/flutter_infra/flutter/$version/';
|
||||
final String url = '${cache.storageBaseUrl}/flutter_infra/flutter/$version/';
|
||||
|
||||
final Directory pkgDir = cache.getCacheDir('pkg');
|
||||
for (String pkgName in getPackageDirs()) {
|
||||
@@ -695,7 +697,7 @@ abstract class EngineCachedArtifact extends CachedArtifact {
|
||||
}
|
||||
}
|
||||
|
||||
final File licenseSource = fs.file(fs.path.join(Cache.flutterRoot, 'LICENSE'));
|
||||
final File licenseSource = cache.getLicenseFile();
|
||||
for (String licenseDir in getLicenseDirs()) {
|
||||
final String licenseDestinationPath = fs.path.join(location.path, licenseDir, 'LICENSE');
|
||||
await licenseSource.copy(licenseDestinationPath);
|
||||
@@ -704,7 +706,7 @@ abstract class EngineCachedArtifact extends CachedArtifact {
|
||||
|
||||
Future<bool> checkForArtifacts(String engineVersion) async {
|
||||
engineVersion ??= version;
|
||||
final String url = '$storageBaseUrl/flutter_infra/flutter/$engineVersion/';
|
||||
final String url = '${cache.storageBaseUrl}/flutter_infra/flutter/$engineVersion/';
|
||||
|
||||
bool exists = false;
|
||||
for (String pkgName in getPackageDirs()) {
|
||||
@@ -1210,7 +1212,7 @@ class IosUsbArtifacts extends CachedArtifact {
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
Uri get archiveUri => Uri.parse('$storageBaseUrl/flutter_infra/ios-usb-dependencies${cache.useUnsignedMacBinaries ? '/unsigned' : ''}/$name/$version/$name.zip');
|
||||
Uri get archiveUri => Uri.parse('${cache.storageBaseUrl}/flutter_infra/ios-usb-dependencies${cache.useUnsignedMacBinaries ? '/unsigned' : ''}/$name/$version/$name.zip');
|
||||
}
|
||||
|
||||
// Many characters are problematic in filenames, especially on Windows.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../aot.dart';
|
||||
import '../application_package.dart';
|
||||
@@ -25,6 +26,7 @@ import '../macos/xcode.dart';
|
||||
import '../plugins.dart';
|
||||
import '../project.dart';
|
||||
import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommandResult;
|
||||
import '../version.dart';
|
||||
import 'build.dart';
|
||||
|
||||
/// Produces a .framework for integration into a host iOS app. The .framework
|
||||
@@ -32,7 +34,7 @@ import 'build.dart';
|
||||
/// be integrated into plain Xcode projects without using or other package
|
||||
/// managers.
|
||||
class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
BuildIOSFrameworkCommand({this.aotBuilder, this.bundleBuilder}) {
|
||||
BuildIOSFrameworkCommand({this.aotBuilder, this.bundleBuilder, this.flutterVersion, this.cache}) {
|
||||
usesTargetOption();
|
||||
usesFlavorOption();
|
||||
usesPubOption();
|
||||
@@ -65,6 +67,9 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
..addFlag('xcframework',
|
||||
help: 'Produce xcframeworks that include all valid architectures (Xcode 11 or later).',
|
||||
)
|
||||
..addFlag('cocoapods',
|
||||
help: 'Produce a Flutter.podspec instead of an engine Flutter.framework (recomended if host app uses CocoaPods).',
|
||||
)
|
||||
..addOption('output',
|
||||
abbr: 'o',
|
||||
valueHelp: 'path/to/directory/',
|
||||
@@ -74,6 +79,8 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
|
||||
AotBuilder aotBuilder;
|
||||
BundleBuilder bundleBuilder;
|
||||
FlutterVersion flutterVersion;
|
||||
Cache cache;
|
||||
|
||||
@override
|
||||
final String name = 'ios-framework';
|
||||
@@ -150,6 +157,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
|
||||
aotBuilder ??= AotBuilder();
|
||||
bundleBuilder ??= BundleBuilder();
|
||||
cache ??= Cache.instance;
|
||||
|
||||
for (BuildMode mode in buildModes) {
|
||||
printStatus('Building framework for $iosProject in ${getNameForBuildMode(mode)} mode...');
|
||||
@@ -162,8 +170,14 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
final Directory iPhoneBuildOutput = modeDirectory.childDirectory('iphoneos');
|
||||
final Directory simulatorBuildOutput = modeDirectory.childDirectory('iphonesimulator');
|
||||
|
||||
// Copy Flutter.framework.
|
||||
await _produceFlutterFramework(outputDirectory, mode, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
|
||||
if (boolArg('cocoapods')) {
|
||||
// FlutterVersion.instance kicks off git processing which can sometimes fail, so don't try it until needed.
|
||||
flutterVersion ??= FlutterVersion.instance;
|
||||
produceFlutterPodspec(mode, modeDirectory);
|
||||
} else {
|
||||
// Copy Flutter.framework.
|
||||
await _produceFlutterFramework(outputDirectory, mode, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
|
||||
}
|
||||
|
||||
// Build aot, create module.framework and copy.
|
||||
await _produceAppFramework(mode, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
|
||||
@@ -194,6 +208,64 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Create podspec that will download and unzip remote engine assets so host apps can leverage CocoaPods
|
||||
/// vendored framework caching.
|
||||
@visibleForTesting
|
||||
void produceFlutterPodspec(BuildMode mode, Directory modeDirectory) {
|
||||
final Status status = logger.startProgress(' ├─Creating Flutter.podspec...', timeout: timeoutConfiguration.fastOperation);
|
||||
try {
|
||||
final GitTagVersion gitTagVersion = flutterVersion.gitTagVersion;
|
||||
if (gitTagVersion.x == null || gitTagVersion.y == null || gitTagVersion.z == null || gitTagVersion.commits != 0) {
|
||||
throwToolExit(
|
||||
'--cocoapods is only supported on the dev, beta, or stable channels. Detected version is ${flutterVersion.frameworkVersion}');
|
||||
}
|
||||
|
||||
// Podspecs use semantic versioning, which don't support hotfixes.
|
||||
// Fake out a semantic version with major.minor.(patch * 100) + hotfix.
|
||||
// A real increasing version is required to prompt CocoaPods to fetch
|
||||
// new artifacts when the source URL changes.
|
||||
final int minorHotfixVersion = gitTagVersion.z * 100 + (gitTagVersion.hotfix ?? 0);
|
||||
|
||||
final File license = cache.getLicenseFile();
|
||||
if (!license.existsSync()) {
|
||||
throwToolExit('Could not find license at ${license.path}');
|
||||
}
|
||||
final String licenseSource = license.readAsStringSync();
|
||||
final String artifactsMode = mode == BuildMode.debug ? 'ios' : 'ios-${mode.name}';
|
||||
|
||||
final String podspecContents = '''
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'Flutter'
|
||||
s.version = '${gitTagVersion.x}.${gitTagVersion.y}.$minorHotfixVersion' # ${flutterVersion.frameworkVersion}
|
||||
s.summary = 'Flutter Engine Framework'
|
||||
s.description = <<-DESC
|
||||
Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
|
||||
This pod vends the iOS Flutter engine framework. It is compatible with application frameworks created with this version of the engine and tools.
|
||||
The pod version matches Flutter version major.minor.(patch * 100) + hotfix.
|
||||
DESC
|
||||
s.homepage = 'https://flutter.dev'
|
||||
s.license = { :type => 'MIT', :text => <<-LICENSE
|
||||
$licenseSource
|
||||
LICENSE
|
||||
}
|
||||
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
|
||||
s.source = { :http => '${cache.storageBaseUrl}/flutter_infra/flutter/${cache.engineRevision}/$artifactsMode/artifacts.zip' }
|
||||
s.documentation_url = 'https://flutter.dev/docs'
|
||||
s.platform = :ios, '8.0'
|
||||
s.vendored_frameworks = 'Flutter.framework'
|
||||
s.prepare_command = <<-CMD
|
||||
unzip Flutter.framework -d Flutter.framework
|
||||
CMD
|
||||
end
|
||||
''';
|
||||
|
||||
final File podspec = modeDirectory.childFile('Flutter.podspec')..createSync(recursive: true);
|
||||
podspec.writeAsStringSync(podspecContents);
|
||||
} finally {
|
||||
status.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _produceFlutterFramework(Directory outputDirectory, BuildMode mode, Directory iPhoneBuildOutput, Directory simulatorBuildOutput, Directory modeDirectory) async {
|
||||
final Status status = logger.startProgress(' ├─Populating Flutter.framework...', timeout: timeoutConfiguration.slowOperation);
|
||||
try {
|
||||
@@ -278,7 +350,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
||||
destinationAppFrameworkDirectory.createSync(recursive: true);
|
||||
|
||||
if (mode == BuildMode.debug) {
|
||||
final Status status = logger.startProgress(' ├─Add placeholder App.framework for debug...', timeout: timeoutConfiguration.fastOperation);
|
||||
final Status status = logger.startProgress(' ├─Adding placeholder App.framework for debug...', timeout: timeoutConfiguration.fastOperation);
|
||||
try {
|
||||
await _produceStubAppFrameworkIfNeeded(mode, iPhoneBuildOutput, simulatorBuildOutput, destinationAppFrameworkDirectory);
|
||||
} finally {
|
||||
|
||||
@@ -20,7 +20,8 @@ import 'globals.dart';
|
||||
class FlutterVersion {
|
||||
FlutterVersion([this._clock = const SystemClock()]) {
|
||||
_frameworkRevision = _runGit(gitLog(<String>['-n', '1', '--pretty=format:%H']).join(' '));
|
||||
_frameworkVersion = GitTagVersion.determine().frameworkVersionFor(_frameworkRevision);
|
||||
_gitTagVersion = GitTagVersion.determine();
|
||||
_frameworkVersion = gitTagVersion.frameworkVersionFor(_frameworkRevision);
|
||||
}
|
||||
|
||||
final SystemClock _clock;
|
||||
@@ -75,6 +76,9 @@ class FlutterVersion {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
GitTagVersion _gitTagVersion;
|
||||
GitTagVersion get gitTagVersion => _gitTagVersion;
|
||||
|
||||
/// The name of the local branch.
|
||||
/// Use getBranchName() to read this.
|
||||
String _branch;
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// 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.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/commands/build_ios_framework.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/version.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
|
||||
void main() {
|
||||
group('build ios-framework', () {
|
||||
group('podspec', () {
|
||||
MemoryFileSystem memoryFileSystem;
|
||||
MockFlutterVersion mockFlutterVersion;
|
||||
MockGitTagVersion mockGitTagVersion;
|
||||
MockCache mockCache;
|
||||
Directory outputDirectory;
|
||||
const String storageBaseUrl = 'https://fake.googleapis.com';
|
||||
const String engineRevision = '0123456789abcdef';
|
||||
File licenseFile;
|
||||
|
||||
setUp(() {
|
||||
memoryFileSystem = MemoryFileSystem();
|
||||
mockFlutterVersion = MockFlutterVersion();
|
||||
mockGitTagVersion = MockGitTagVersion();
|
||||
mockCache = MockCache();
|
||||
|
||||
when(mockFlutterVersion.gitTagVersion).thenReturn(mockGitTagVersion);
|
||||
outputDirectory = fs.systemTempDirectory
|
||||
.createTempSync('flutter_build_ios_framework_test_output.')
|
||||
.childDirectory('Debug')
|
||||
..createSync();
|
||||
|
||||
when(mockCache.storageBaseUrl).thenReturn(storageBaseUrl);
|
||||
when(mockCache.engineRevision).thenReturn(engineRevision);
|
||||
licenseFile = memoryFileSystem.file('LICENSE');
|
||||
when(mockCache.getLicenseFile()).thenReturn(licenseFile);
|
||||
});
|
||||
|
||||
testUsingContext('version unknown', () async {
|
||||
const String frameworkVersion = '0.0.0-unknown';
|
||||
when(mockFlutterVersion.frameworkVersion).thenReturn(frameworkVersion);
|
||||
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
|
||||
expect(() => command.produceFlutterPodspec(BuildMode.debug, outputDirectory),
|
||||
throwsToolExit(message: 'Detected version is $frameworkVersion'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('throws when not on a released version', () async {
|
||||
const String frameworkVersion = 'v1.13.10+hotfix-pre.2';
|
||||
when(mockFlutterVersion.frameworkVersion).thenReturn(frameworkVersion);
|
||||
|
||||
when(mockGitTagVersion.x).thenReturn(1);
|
||||
when(mockGitTagVersion.y).thenReturn(13);
|
||||
when(mockGitTagVersion.z).thenReturn(10);
|
||||
when(mockGitTagVersion.hotfix).thenReturn(13);
|
||||
when(mockGitTagVersion.commits).thenReturn(2);
|
||||
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
|
||||
expect(() => command.produceFlutterPodspec(BuildMode.debug, outputDirectory),
|
||||
throwsToolExit(message: 'Detected version is $frameworkVersion'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('throws when license not found', () async {
|
||||
when(mockGitTagVersion.x).thenReturn(1);
|
||||
when(mockGitTagVersion.y).thenReturn(13);
|
||||
when(mockGitTagVersion.z).thenReturn(10);
|
||||
when(mockGitTagVersion.hotfix).thenReturn(13);
|
||||
when(mockGitTagVersion.commits).thenReturn(0);
|
||||
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
|
||||
expect(() => command.produceFlutterPodspec(BuildMode.debug, outputDirectory),
|
||||
throwsToolExit(message: 'Could not find license'));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
group('is created', () {
|
||||
const String frameworkVersion = 'v1.13.11+hotfix.13';
|
||||
const String licenseText = 'This is the license!';
|
||||
|
||||
setUp(() {
|
||||
when(mockGitTagVersion.x).thenReturn(1);
|
||||
when(mockGitTagVersion.y).thenReturn(13);
|
||||
when(mockGitTagVersion.z).thenReturn(11);
|
||||
when(mockGitTagVersion.hotfix).thenReturn(13);
|
||||
when(mockGitTagVersion.commits).thenReturn(0);
|
||||
|
||||
when(mockFlutterVersion.frameworkVersion).thenReturn(frameworkVersion);
|
||||
|
||||
licenseFile
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(licenseText);
|
||||
});
|
||||
|
||||
testUsingContext('contains license and version', () async {
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
command.produceFlutterPodspec(BuildMode.debug, outputDirectory);
|
||||
|
||||
final File expectedPodspec = outputDirectory.childFile('Flutter.podspec');
|
||||
final String podspecContents = expectedPodspec.readAsStringSync();
|
||||
expect(podspecContents, contains('\'1.13.1113\''));
|
||||
expect(podspecContents, contains('# $frameworkVersion'));
|
||||
expect(podspecContents, contains(licenseText));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('debug URL', () async {
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
command.produceFlutterPodspec(BuildMode.debug, outputDirectory);
|
||||
|
||||
final File expectedPodspec = outputDirectory.childFile('Flutter.podspec');
|
||||
final String podspecContents = expectedPodspec.readAsStringSync();
|
||||
expect(podspecContents, contains('\'$storageBaseUrl/flutter_infra/flutter/$engineRevision/ios/artifacts.zip\''));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('profile URL', () async {
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
command.produceFlutterPodspec(BuildMode.profile, outputDirectory);
|
||||
|
||||
final File expectedPodspec = outputDirectory.childFile('Flutter.podspec');
|
||||
final String podspecContents = expectedPodspec.readAsStringSync();
|
||||
expect(podspecContents, contains('\'$storageBaseUrl/flutter_infra/flutter/$engineRevision/ios-profile/artifacts.zip\''));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('release URL', () async {
|
||||
final BuildIOSFrameworkCommand command = BuildIOSFrameworkCommand(
|
||||
flutterVersion: mockFlutterVersion,
|
||||
cache: mockCache
|
||||
);
|
||||
command.produceFlutterPodspec(BuildMode.release, outputDirectory);
|
||||
|
||||
final File expectedPodspec = outputDirectory.childFile('Flutter.podspec');
|
||||
final String podspecContents = expectedPodspec.readAsStringSync();
|
||||
expect(podspecContents, contains('\'$storageBaseUrl/flutter_infra/flutter/$engineRevision/ios-release/artifacts.zip\''));
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class MockFlutterVersion extends Mock implements FlutterVersion {}
|
||||
class MockGitTagVersion extends Mock implements GitTagVersion {}
|
||||
class MockCache extends Mock implements Cache {}
|
||||
@@ -230,9 +230,7 @@ void main() {
|
||||
'FLUTTER_STORAGE_BASE_URL': ' http://foo',
|
||||
});
|
||||
final Cache cache = Cache();
|
||||
final CachedArtifact artifact = MaterialFonts(cache);
|
||||
|
||||
expect(() => artifact.storageBaseUrl, throwsA(isInstanceOf<ToolExit>()));
|
||||
expect(() => cache.storageBaseUrl, throwsA(isInstanceOf<ToolExit>()));
|
||||
}, overrides: <Type, Generator>{
|
||||
Platform: () => MockPlatform(),
|
||||
});
|
||||
|
||||
@@ -680,6 +680,9 @@ class FakeFlutterVersion implements FlutterVersion {
|
||||
@override
|
||||
String get frameworkVersion => null;
|
||||
|
||||
@override
|
||||
GitTagVersion get gitTagVersion => null;
|
||||
|
||||
@override
|
||||
String getBranchName({bool redactUnknownBranches = false}) {
|
||||
return 'master';
|
||||
@@ -829,6 +832,9 @@ class FakeCache implements Cache {
|
||||
@override
|
||||
String get dartSdkVersion => null;
|
||||
|
||||
@override
|
||||
String get storageBaseUrl => null;
|
||||
|
||||
@override
|
||||
MapEntry<String, String> get dyLdLibEntry => null;
|
||||
|
||||
@@ -860,6 +866,11 @@ class FakeCache implements Cache {
|
||||
return fs.currentDirectory;
|
||||
}
|
||||
|
||||
@override
|
||||
File getLicenseFile() {
|
||||
return fs.currentDirectory.childFile('LICENSE');
|
||||
}
|
||||
|
||||
@override
|
||||
File getStampFileFor(String artifactName) {
|
||||
throw UnsupportedError('Not supported in the fake Cache');
|
||||
|
||||
Reference in New Issue
Block a user