Unverified Commit a633f3df authored by Lau Ching Jun's avatar Lau Ching Jun Committed by GitHub

Add ability for PrebuiltWindowsApp to accept a zip archive. (#103918)

parent d54cdf9e
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:archive/archive.dart';
import '../application_package.dart';
import '../base/file_system.dart';
import '../base/utils.dart';
......@@ -20,12 +22,56 @@ abstract class WindowsApp extends ApplicationPackage {
);
}
/// Creates a new [WindowsApp] from an existing executable.
/// Creates a new [WindowsApp] from an existing executable or a zip archive.
///
/// `applicationBinary` is the path to the executable.
factory WindowsApp.fromPrebuiltApp(FileSystemEntity applicationBinary) {
/// `applicationBinary` is the path to the executable or the zipped archive.
static WindowsApp? fromPrebuiltApp(FileSystemEntity applicationBinary) {
if (!applicationBinary.existsSync()) {
globals.printError('File "${applicationBinary.path}" does not exist.');
return null;
}
if (applicationBinary.path.endsWith('.exe')) {
return PrebuiltWindowsApp(
executable: applicationBinary.path,
applicationPackage: applicationBinary,
);
}
if (!applicationBinary.path.endsWith('.zip')) {
// Unknown file type
globals.printError('Unknown windows application type.');
return null;
}
// Try to unpack as a zip.
final Directory tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_app.');
try {
globals.os.unzip(globals.fs.file(applicationBinary), tempDir);
} on ArchiveException {
globals.printError('Invalid prebuilt Windows app. Unable to extract from archive.');
return null;
}
final List<FileSystemEntity> exeFilesFound = <FileSystemEntity>[];
for (final FileSystemEntity file in tempDir.listSync()) {
if (file.basename.endsWith('.exe')) {
exeFilesFound.add(file);
}
}
if (exeFilesFound.isEmpty) {
globals.printError('Cannot find .exe files in the zip archive.');
return null;
}
if (exeFilesFound.length > 1) {
globals.printError('Archive "${applicationBinary.path}" contains more than one .exe files.');
return null;
}
return PrebuiltWindowsApp(
executable: applicationBinary.path,
executable: exeFilesFound.single.path,
applicationPackage: applicationBinary,
);
}
......@@ -35,9 +81,10 @@ abstract class WindowsApp extends ApplicationPackage {
String executable(BuildMode buildMode);
}
class PrebuiltWindowsApp extends WindowsApp {
class PrebuiltWindowsApp extends WindowsApp implements PrebuiltApplicationPackage {
PrebuiltWindowsApp({
required String executable,
required this.applicationPackage,
}) : _executable = executable,
super(projectBundleId: executable);
......@@ -48,6 +95,9 @@ class PrebuiltWindowsApp extends WindowsApp {
@override
String get name => _executable;
@override
final FileSystemEntity applicationPackage;
}
class BuildableWindowsApp extends WindowsApp {
......
// 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: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/base/os.dart';
import 'package:flutter_tools/src/windows/application_package.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/context.dart';
void main() {
group('PrebuiltWindowsApp', () {
FakeOperatingSystemUtils os;
FileSystem fileSystem;
BufferLogger logger;
final Map<Type, Generator> overrides = <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(),
OperatingSystemUtils: () => os,
Logger: () => logger,
};
setUp(() {
fileSystem = MemoryFileSystem.test();
os = FakeOperatingSystemUtils();
logger = BufferLogger.test();
});
testUsingContext('Error on non-existing exe file', () {
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.exe')) as PrebuiltWindowsApp;
expect(windowsApp, isNull);
expect(logger.errorText, contains('File "not_existing.exe" does not exist.'));
}, overrides: overrides);
testUsingContext('Success on exe file', () {
fileSystem.file('file.exe').createSync();
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('file.exe')) as PrebuiltWindowsApp;
expect(windowsApp.name, 'file.exe');
}, overrides: overrides);
testUsingContext('Error on non-existing zip file', () {
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.zip')) as PrebuiltWindowsApp;
expect(windowsApp, isNull);
expect(logger.errorText, contains('File "not_existing.zip" does not exist.'));
}, overrides: overrides);
testUsingContext('Bad zipped app, no payload dir', () {
fileSystem.file('app.zip').createSync();
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;
expect(windowsApp, isNull);
expect(logger.errorText, contains('Cannot find .exe files in the zip archive.'));
}, overrides: overrides);
testUsingContext('Bad zipped app, two .exe files', () {
fileSystem.file('app.zip').createSync();
os.unzipOverride = (File zipFile, Directory targetDirectory) {
if (zipFile.path != 'app.zip') {
return;
}
final String exePath1 = fileSystem.path.join(targetDirectory.path, 'app1.exe');
final String exePath2 = fileSystem.path.join(targetDirectory.path, 'app2.exe');
fileSystem.directory(exePath1).createSync(recursive: true);
fileSystem.directory(exePath2).createSync(recursive: true);
};
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;
expect(windowsApp, isNull);
expect(logger.errorText, contains('Archive "app.zip" contains more than one .exe files.'));
}, overrides: overrides);
testUsingContext('Success with zipped app', () {
fileSystem.file('app.zip').createSync();
String exePath;
os.unzipOverride = (File zipFile, Directory targetDirectory) {
if (zipFile.path != 'app.zip') {
return;
}
exePath = fileSystem.path.join(targetDirectory.path, 'app.exe');
fileSystem.directory(exePath).createSync(recursive: true);
};
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('app.zip')) as PrebuiltWindowsApp;
expect(logger.errorText, isEmpty);
expect(windowsApp.name, exePath);
expect(windowsApp.applicationPackage.path, 'app.zip');
}, overrides: overrides);
testUsingContext('Error on unknown file type', () {
fileSystem.file('not_existing.app').createSync();
final PrebuiltWindowsApp windowsApp = WindowsApp.fromPrebuiltApp(fileSystem.file('not_existing.app')) as PrebuiltWindowsApp;
expect(windowsApp, isNull);
expect(logger.errorText, contains('Unknown windows application type.'));
}, overrides: overrides);
});
}
class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils {
FakeOperatingSystemUtils();
void Function(File, Directory) unzipOverride;
@override
void unzip(File file, Directory targetDirectory) {
unzipOverride?.call(file, targetDirectory);
}
}
......@@ -23,7 +23,8 @@ import '../../src/fakes.dart';
void main() {
testWithoutContext('WindowsDevice defaults', () async {
final WindowsDevice windowsDevice = setUpWindowsDevice();
final PrebuiltWindowsApp windowsApp = PrebuiltWindowsApp(executable: 'foo');
final File dummyFile = MemoryFileSystem.test().file('dummy');
final PrebuiltWindowsApp windowsApp = PrebuiltWindowsApp(executable: 'foo', applicationPackage: dummyFile);
expect(await windowsDevice.targetPlatform, TargetPlatform.windows_x64);
expect(windowsDevice.name, 'Windows');
......
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