feat: support field_table data in link supplement (#3008)
This commit is contained in:
@@ -1 +1 @@
|
|||||||
3f9cefb45389b72ff073ddf305fe0939f822143b
|
b14323b05f28b2c72b34f57c8059ec3001d65712
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ words:
|
|||||||
- dylib
|
- dylib
|
||||||
- endtemplate
|
- endtemplate
|
||||||
- Entra
|
- Entra
|
||||||
|
- eseidel
|
||||||
- exitcode
|
- exitcode
|
||||||
- exportoptions
|
- exportoptions
|
||||||
- felangel
|
- felangel
|
||||||
|
|||||||
@@ -43,20 +43,6 @@ class IosFrameworkPatcher extends Patcher {
|
|||||||
String get _aotOutputPath =>
|
String get _aotOutputPath =>
|
||||||
p.join(shorebirdEnv.buildDirectory.path, 'out.aot');
|
p.join(shorebirdEnv.buildDirectory.path, 'out.aot');
|
||||||
|
|
||||||
String get _patchClassTableLinkInfoFile => p.join(
|
|
||||||
shorebirdEnv.buildDirectory.path,
|
|
||||||
'ios',
|
|
||||||
'shorebird',
|
|
||||||
'App.ct.link',
|
|
||||||
);
|
|
||||||
|
|
||||||
String get _patchClassTableLinkDebugInfoPath => p.join(
|
|
||||||
shorebirdEnv.buildDirectory.path,
|
|
||||||
'ios',
|
|
||||||
'shorebird',
|
|
||||||
'App.class_table.json',
|
|
||||||
);
|
|
||||||
|
|
||||||
String get _vmcodeOutputPath =>
|
String get _vmcodeOutputPath =>
|
||||||
p.join(shorebirdEnv.buildDirectory.path, 'out.vmcode');
|
p.join(shorebirdEnv.buildDirectory.path, 'out.vmcode');
|
||||||
|
|
||||||
@@ -161,27 +147,12 @@ class IosFrameworkPatcher extends Patcher {
|
|||||||
releaseXcframeworkPath = tempDir.path;
|
releaseXcframeworkPath = tempDir.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
File? releaseClassTableLinkInfoFile;
|
final releaseSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
File? releaseClassTableLinkDebugInfoFile;
|
|
||||||
if (supplementArtifact != null) {
|
if (supplementArtifact != null) {
|
||||||
final tempDir = Directory.systemTemp.createTempSync();
|
|
||||||
await artifactManager.extractZip(
|
await artifactManager.extractZip(
|
||||||
zipFile: supplementArtifact,
|
zipFile: supplementArtifact,
|
||||||
outputDirectory: tempDir,
|
outputDirectory: releaseSupplementDir,
|
||||||
);
|
);
|
||||||
releaseClassTableLinkInfoFile = File(p.join(tempDir.path, 'App.ct.link'));
|
|
||||||
if (!releaseClassTableLinkInfoFile.existsSync()) {
|
|
||||||
logger.err('Unable to find class table link info file');
|
|
||||||
throw ProcessExit(ExitCode.software.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseClassTableLinkDebugInfoFile = File(
|
|
||||||
p.join(tempDir.path, 'App.class_table.json'),
|
|
||||||
);
|
|
||||||
if (!releaseClassTableLinkDebugInfoFile.existsSync()) {
|
|
||||||
logger.err('Unable to find class table link debug info file');
|
|
||||||
throw ProcessExit(ExitCode.software.code);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unzipProgress.complete(
|
unzipProgress.complete(
|
||||||
@@ -194,30 +165,15 @@ class IosFrameworkPatcher extends Patcher {
|
|||||||
final aotSnapshotFile = File(
|
final aotSnapshotFile = File(
|
||||||
p.join(shorebirdEnv.getShorebirdProjectRoot()!.path, 'build', 'out.aot'),
|
p.join(shorebirdEnv.getShorebirdProjectRoot()!.path, 'build', 'out.aot'),
|
||||||
);
|
);
|
||||||
|
// TODO(eseidel): Drop support for builds before the linker.
|
||||||
final useLinker = AotTools.usesLinker(shorebirdEnv.flutterRevision);
|
final useLinker = AotTools.usesLinker(shorebirdEnv.flutterRevision);
|
||||||
if (useLinker) {
|
if (useLinker) {
|
||||||
// If we're using a newer version of the linker, we need to also copy the
|
apple.copySupplementFilesToSnapshotDirs(
|
||||||
// necessary class table link information alongside the snapshots.
|
releaseSupplementDir: releaseSupplementDir,
|
||||||
if (releaseClassTableLinkInfoFile != null &&
|
releaseSnapshotDir: releaseArtifactFile.parent,
|
||||||
releaseClassTableLinkDebugInfoFile != null) {
|
patchSupplementDir: shorebirdEnv.iosSupplementDirectory,
|
||||||
// Copy the release's class table link info file next to the release
|
patchSnapshotDir: shorebirdEnv.buildDirectory,
|
||||||
// snapshot so that it can be used to generate a patch.
|
);
|
||||||
releaseClassTableLinkInfoFile.copySync(
|
|
||||||
p.join(releaseArtifactFile.parent.path, 'App.ct.link'),
|
|
||||||
);
|
|
||||||
releaseClassTableLinkDebugInfoFile.copySync(
|
|
||||||
p.join(releaseArtifactFile.parent.path, 'App.class_table.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy the patch's class table link info file to the build directory
|
|
||||||
// so that it can be used to generate a patch.
|
|
||||||
File(
|
|
||||||
_patchClassTableLinkInfoFile,
|
|
||||||
).copySync(p.join(shorebirdEnv.buildDirectory.path, 'out.ct.link'));
|
|
||||||
File(_patchClassTableLinkDebugInfoPath).copySync(
|
|
||||||
p.join(shorebirdEnv.buildDirectory.path, 'out.class_table.json'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await apple.runLinker(
|
await apple.runLinker(
|
||||||
kernelFile: File(_appDillCopyPath),
|
kernelFile: File(_appDillCopyPath),
|
||||||
|
|||||||
@@ -43,20 +43,6 @@ class IosPatcher extends Patcher {
|
|||||||
required super.target,
|
required super.target,
|
||||||
});
|
});
|
||||||
|
|
||||||
String get _patchClassTableLinkInfoPath => p.join(
|
|
||||||
shorebirdEnv.buildDirectory.path,
|
|
||||||
'ios',
|
|
||||||
'shorebird',
|
|
||||||
'App.ct.link',
|
|
||||||
);
|
|
||||||
|
|
||||||
String get _patchClassTableLinkDebugInfoPath => p.join(
|
|
||||||
shorebirdEnv.buildDirectory.path,
|
|
||||||
'ios',
|
|
||||||
'shorebird',
|
|
||||||
'App.class_table.json',
|
|
||||||
);
|
|
||||||
|
|
||||||
String get _aotOutputPath =>
|
String get _aotOutputPath =>
|
||||||
p.join(shorebirdEnv.buildDirectory.path, 'out.aot');
|
p.join(shorebirdEnv.buildDirectory.path, 'out.aot');
|
||||||
|
|
||||||
@@ -243,27 +229,12 @@ For more information see: ${supportedFlutterVersionsUrl.toLink()}''');
|
|||||||
releaseXcarchivePath = tempDir.path;
|
releaseXcarchivePath = tempDir.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
File? releaseClassTableLinkInfoFile;
|
final releaseSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
File? releaseClassTableLinkDebugInfoFile;
|
|
||||||
if (supplementArtifact != null) {
|
if (supplementArtifact != null) {
|
||||||
final tempDir = Directory.systemTemp.createTempSync();
|
|
||||||
await artifactManager.extractZip(
|
await artifactManager.extractZip(
|
||||||
zipFile: supplementArtifact,
|
zipFile: supplementArtifact,
|
||||||
outputDirectory: tempDir,
|
outputDirectory: releaseSupplementDir,
|
||||||
);
|
);
|
||||||
releaseClassTableLinkInfoFile = File(p.join(tempDir.path, 'App.ct.link'));
|
|
||||||
if (!releaseClassTableLinkInfoFile.existsSync()) {
|
|
||||||
logger.err('Unable to find class table link info file');
|
|
||||||
throw ProcessExit(ExitCode.software.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseClassTableLinkDebugInfoFile = File(
|
|
||||||
p.join(tempDir.path, 'App.class_table.json'),
|
|
||||||
);
|
|
||||||
if (!releaseClassTableLinkDebugInfoFile.existsSync()) {
|
|
||||||
logger.err('Unable to find class table link debug info file');
|
|
||||||
throw ProcessExit(ExitCode.software.code);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unzipProgress.complete();
|
unzipProgress.complete();
|
||||||
@@ -280,28 +251,12 @@ For more information see: ${supportedFlutterVersionsUrl.toLink()}''');
|
|||||||
|
|
||||||
final useLinker = AotTools.usesLinker(shorebirdEnv.flutterRevision);
|
final useLinker = AotTools.usesLinker(shorebirdEnv.flutterRevision);
|
||||||
if (useLinker) {
|
if (useLinker) {
|
||||||
// If we're using a newer version of the linker, we need to also copy the
|
apple.copySupplementFilesToSnapshotDirs(
|
||||||
// necessary class table link information alongside the snapshots.
|
releaseSupplementDir: releaseSupplementDir,
|
||||||
if (releaseClassTableLinkInfoFile != null &&
|
releaseSnapshotDir: releaseArtifactFile.parent,
|
||||||
releaseClassTableLinkDebugInfoFile != null) {
|
patchSupplementDir: shorebirdEnv.iosSupplementDirectory,
|
||||||
// Copy the release's class table link info file next to the release
|
patchSnapshotDir: shorebirdEnv.buildDirectory,
|
||||||
// snapshot so that it can be used to generate a patch.
|
);
|
||||||
releaseClassTableLinkInfoFile.copySync(
|
|
||||||
p.join(releaseArtifactFile.parent.path, 'App.ct.link'),
|
|
||||||
);
|
|
||||||
releaseClassTableLinkDebugInfoFile.copySync(
|
|
||||||
p.join(releaseArtifactFile.parent.path, 'App.class_table.json'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy the patch's class table link info file to the build directory
|
|
||||||
// so that it can be used to generate a patch.
|
|
||||||
File(
|
|
||||||
_patchClassTableLinkInfoPath,
|
|
||||||
).copySync(p.join(shorebirdEnv.buildDirectory.path, 'out.ct.link'));
|
|
||||||
File(_patchClassTableLinkDebugInfoPath).copySync(
|
|
||||||
p.join(shorebirdEnv.buildDirectory.path, 'out.class_table.json'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final (:exitCode, :linkPercentage) = await apple.runLinker(
|
final (:exitCode, :linkPercentage) = await apple.runLinker(
|
||||||
kernelFile: File(_appDillCopyPath),
|
kernelFile: File(_appDillCopyPath),
|
||||||
|
|||||||
@@ -110,6 +110,60 @@ Apple get apple => read(appleRef);
|
|||||||
|
|
||||||
/// A class that provides information about the iOS platform.
|
/// A class that provides information about the iOS platform.
|
||||||
class Apple {
|
class Apple {
|
||||||
|
/// Copies the supplement files into the build directory.
|
||||||
|
/// Currently we run gen_snapshot from `flutter`, both for the release and
|
||||||
|
/// patch builds. Both times it produces supplement files in a directory.
|
||||||
|
/// In the release case, these files are zipped up and stored as an artifact
|
||||||
|
/// on our servers for later use. In the patch case, they were created on
|
||||||
|
/// disk just before this call.
|
||||||
|
/// In both cases we need to copy the supplement files from these directories
|
||||||
|
/// to right next to where the snapshot files are before calling into
|
||||||
|
/// `aot_tools` to link the two snapshots together.
|
||||||
|
// TODO(eseidel): We should pass the entire supplement directories to
|
||||||
|
// `aot_tools` rather than having to know the contents within `shorebird`.
|
||||||
|
void copySupplementFilesToSnapshotDirs({
|
||||||
|
required Directory releaseSupplementDir,
|
||||||
|
required Directory releaseSnapshotDir,
|
||||||
|
required Directory patchSupplementDir,
|
||||||
|
required Directory patchSnapshotDir,
|
||||||
|
}) {
|
||||||
|
// All known supplement files names seen across all Flutter versions.
|
||||||
|
final supplementFileNames = <String>[
|
||||||
|
'App.ct.link',
|
||||||
|
'App.class_table.json',
|
||||||
|
'App.ft.link',
|
||||||
|
'App.field_table.json',
|
||||||
|
];
|
||||||
|
|
||||||
|
// This uses maybeCopy because not all versions of gen_snapshot/aot_tools
|
||||||
|
// use the same supplement files. At the `shorebird` level we don't know
|
||||||
|
// which files should be present, so we just try to copy all.
|
||||||
|
void maybeCopy(File file, Directory destDir, {String? newBaseName}) {
|
||||||
|
if (!file.existsSync()) return;
|
||||||
|
final baseName = p.basename(file.path);
|
||||||
|
final destName =
|
||||||
|
newBaseName != null
|
||||||
|
? baseName.replaceFirst('App', newBaseName)
|
||||||
|
: baseName;
|
||||||
|
file.copySync(p.join(destDir.path, destName));
|
||||||
|
}
|
||||||
|
|
||||||
|
final releaseSupplementFiles = supplementFileNames.map(
|
||||||
|
(name) => File(p.join(releaseSupplementDir.path, name)),
|
||||||
|
);
|
||||||
|
for (final file in releaseSupplementFiles) {
|
||||||
|
maybeCopy(file, releaseSnapshotDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
final patchSupplementFiles = supplementFileNames.map(
|
||||||
|
(name) => File(p.join(patchSupplementDir.path, name)),
|
||||||
|
);
|
||||||
|
const patchSnapshotBaseName = 'out';
|
||||||
|
for (final file in patchSupplementFiles) {
|
||||||
|
maybeCopy(file, patchSnapshotDir, newBaseName: patchSnapshotBaseName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the set of flavors for the Xcode project associated with
|
/// Returns the set of flavors for the Xcode project associated with
|
||||||
/// [platform], if this project has that platform configured.
|
/// [platform], if this project has that platform configured.
|
||||||
Set<String>? flavors({required ApplePlatform platform}) {
|
Set<String>? flavors({required ApplePlatform platform}) {
|
||||||
@@ -155,6 +209,7 @@ class Apple {
|
|||||||
.toSet();
|
.toSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(eseidel): Move this into a "linker" class rather than Apple.
|
||||||
/// Runs the linking step to minimize differences between patch and release
|
/// Runs the linking step to minimize differences between patch and release
|
||||||
/// and maximize code that can be executed on the CPU.
|
/// and maximize code that can be executed on the CPU.
|
||||||
Future<LinkResult> runLinker({
|
Future<LinkResult> runLinker({
|
||||||
|
|||||||
@@ -98,6 +98,11 @@ class ShorebirdEnv {
|
|||||||
return Directory(p.join(getFlutterProjectRoot()!.path, 'build'));
|
return Directory(p.join(getFlutterProjectRoot()!.path, 'build'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Where the link supplement files are stored.
|
||||||
|
// TODO(eseidel): Make this not iOS specific.
|
||||||
|
Directory get iosSupplementDirectory =>
|
||||||
|
Directory(p.join(buildDirectory.path, 'ios', 'shorebird'));
|
||||||
|
|
||||||
/// The `shorebird.yaml` file for this project.
|
/// The `shorebird.yaml` file for this project.
|
||||||
File getShorebirdYamlFile({required Directory cwd}) {
|
File getShorebirdYamlFile({required Directory cwd}) {
|
||||||
return File(p.join(cwd.path, 'shorebird.yaml'));
|
return File(p.join(cwd.path, 'shorebird.yaml'));
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ void main() {
|
|||||||
when(
|
when(
|
||||||
() => shorebirdEnv.buildDirectory,
|
() => shorebirdEnv.buildDirectory,
|
||||||
).thenReturn(Directory(p.join(projectRoot.path, 'build')));
|
).thenReturn(Directory(p.join(projectRoot.path, 'build')));
|
||||||
|
when(() => shorebirdEnv.iosSupplementDirectory).thenReturn(
|
||||||
|
Directory(p.join(projectRoot.path, 'build', 'shorebird', 'ios')),
|
||||||
|
);
|
||||||
when(
|
when(
|
||||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||||
).thenReturn(projectRoot);
|
).thenReturn(projectRoot);
|
||||||
@@ -803,72 +806,6 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
group('when class table link info is not present', () {
|
|
||||||
setUp(() {
|
|
||||||
when(
|
|
||||||
() => artifactManager.extractZip(
|
|
||||||
zipFile: supplementArtifactFile,
|
|
||||||
outputDirectory: any(named: 'outputDirectory'),
|
|
||||||
),
|
|
||||||
).thenAnswer((invocation) async {});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exits with code 70', () async {
|
|
||||||
await expectLater(
|
|
||||||
() => runWithOverrides(
|
|
||||||
() => patcher.createPatchArtifacts(
|
|
||||||
appId: appId,
|
|
||||||
releaseId: releaseId,
|
|
||||||
releaseArtifact: releaseArtifactFile,
|
|
||||||
supplementArtifact: supplementArtifactFile,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
exitsWithCode(ExitCode.software),
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(
|
|
||||||
() => logger.err('Unable to find class table link info file'),
|
|
||||||
).called(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('when debug info is missing', () {
|
|
||||||
setUp(() {
|
|
||||||
when(
|
|
||||||
() => artifactManager.extractZip(
|
|
||||||
zipFile: supplementArtifactFile,
|
|
||||||
outputDirectory: any(named: 'outputDirectory'),
|
|
||||||
),
|
|
||||||
).thenAnswer((invocation) async {
|
|
||||||
final outDir =
|
|
||||||
invocation.namedArguments[#outputDirectory] as Directory;
|
|
||||||
File(
|
|
||||||
p.join(outDir.path, 'App.ct.link'),
|
|
||||||
).createSync(recursive: true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exits with code 70', () async {
|
|
||||||
await expectLater(
|
|
||||||
() => runWithOverrides(
|
|
||||||
() => patcher.createPatchArtifacts(
|
|
||||||
appId: appId,
|
|
||||||
releaseId: releaseId,
|
|
||||||
releaseArtifact: releaseArtifactFile,
|
|
||||||
supplementArtifact: supplementArtifactFile,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
exitsWithCode(ExitCode.software),
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(
|
|
||||||
() => logger.err(
|
|
||||||
'Unable to find class table link debug info file',
|
|
||||||
),
|
|
||||||
).called(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('when class table link info & debug info are present', () {
|
group('when class table link info & debug info are present', () {
|
||||||
setUp(() {
|
setUp(() {
|
||||||
when(
|
when(
|
||||||
|
|||||||
@@ -143,6 +143,9 @@ void main() {
|
|||||||
when(
|
when(
|
||||||
() => shorebirdEnv.buildDirectory,
|
() => shorebirdEnv.buildDirectory,
|
||||||
).thenReturn(Directory(p.join(projectRoot.path, 'build')));
|
).thenReturn(Directory(p.join(projectRoot.path, 'build')));
|
||||||
|
when(() => shorebirdEnv.iosSupplementDirectory).thenReturn(
|
||||||
|
Directory(p.join(projectRoot.path, 'build', 'shorebird', 'ios')),
|
||||||
|
);
|
||||||
|
|
||||||
when(aotTools.isLinkDebugInfoSupported).thenAnswer((_) async => false);
|
when(aotTools.isLinkDebugInfoSupported).thenAnswer((_) async => false);
|
||||||
|
|
||||||
@@ -1126,72 +1129,6 @@ For more information see: ${supportedFlutterVersionsUrl.toLink()}'''),
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
group('when class table link info is not present', () {
|
|
||||||
setUp(() {
|
|
||||||
when(
|
|
||||||
() => artifactManager.extractZip(
|
|
||||||
zipFile: supplementArtifactFile,
|
|
||||||
outputDirectory: any(named: 'outputDirectory'),
|
|
||||||
),
|
|
||||||
).thenAnswer((invocation) async {});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exits with code 70', () async {
|
|
||||||
await expectLater(
|
|
||||||
() => runWithOverrides(
|
|
||||||
() => patcher.createPatchArtifacts(
|
|
||||||
appId: appId,
|
|
||||||
releaseId: releaseId,
|
|
||||||
releaseArtifact: releaseArtifactFile,
|
|
||||||
supplementArtifact: supplementArtifactFile,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
exitsWithCode(ExitCode.software),
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(
|
|
||||||
() => logger.err('Unable to find class table link info file'),
|
|
||||||
).called(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('when debug info is missing', () {
|
|
||||||
setUp(() {
|
|
||||||
when(
|
|
||||||
() => artifactManager.extractZip(
|
|
||||||
zipFile: supplementArtifactFile,
|
|
||||||
outputDirectory: any(named: 'outputDirectory'),
|
|
||||||
),
|
|
||||||
).thenAnswer((invocation) async {
|
|
||||||
final outDir =
|
|
||||||
invocation.namedArguments[#outputDirectory] as Directory;
|
|
||||||
File(
|
|
||||||
p.join(outDir.path, 'App.ct.link'),
|
|
||||||
).createSync(recursive: true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exits with code 70', () async {
|
|
||||||
await expectLater(
|
|
||||||
() => runWithOverrides(
|
|
||||||
() => patcher.createPatchArtifacts(
|
|
||||||
appId: appId,
|
|
||||||
releaseId: releaseId,
|
|
||||||
releaseArtifact: releaseArtifactFile,
|
|
||||||
supplementArtifact: supplementArtifactFile,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
exitsWithCode(ExitCode.software),
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(
|
|
||||||
() => logger.err(
|
|
||||||
'Unable to find class table link debug info file',
|
|
||||||
),
|
|
||||||
).called(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('when class table link info & debug info are present', () {
|
group('when class table link info & debug info are present', () {
|
||||||
setUp(() {
|
setUp(() {
|
||||||
when(
|
when(
|
||||||
|
|||||||
@@ -92,6 +92,65 @@ To add macOS, run "flutter create . --platforms macos"''');
|
|||||||
).thenReturn(projectRoot);
|
).thenReturn(projectRoot);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('copySupplementFilesToSnapshotDirs', () {
|
||||||
|
test('copies all files next to snapshots', () {
|
||||||
|
final names = [
|
||||||
|
'App.class_table.json',
|
||||||
|
'App.field_table.json',
|
||||||
|
'App.ct.link',
|
||||||
|
'App.ft.link',
|
||||||
|
];
|
||||||
|
|
||||||
|
void createFiles(Directory dir) {
|
||||||
|
for (final name in names) {
|
||||||
|
File(p.join(dir.path, name)).createSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final releaseSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
|
final patchSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
|
createFiles(releaseSupplementDir);
|
||||||
|
createFiles(patchSupplementDir);
|
||||||
|
|
||||||
|
final releaseSnapshotDir = Directory.systemTemp.createTempSync();
|
||||||
|
final patchSnapshotDir = Directory.systemTemp.createTempSync();
|
||||||
|
apple.copySupplementFilesToSnapshotDirs(
|
||||||
|
releaseSupplementDir: releaseSupplementDir,
|
||||||
|
releaseSnapshotDir: releaseSnapshotDir,
|
||||||
|
patchSupplementDir: patchSupplementDir,
|
||||||
|
patchSnapshotDir: patchSnapshotDir,
|
||||||
|
);
|
||||||
|
expect(Directory(releaseSnapshotDir.path).listSync(), hasLength(4));
|
||||||
|
expect(Directory(patchSnapshotDir.path).listSync(), hasLength(4));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('copies only some files next to snapshots', () {
|
||||||
|
final names = ['App.class_table.json', 'App.ct.link', 'ignored.txt'];
|
||||||
|
|
||||||
|
void createFiles(Directory dir) {
|
||||||
|
for (final name in names) {
|
||||||
|
File(p.join(dir.path, name)).createSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final releaseSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
|
final patchSupplementDir = Directory.systemTemp.createTempSync();
|
||||||
|
createFiles(releaseSupplementDir);
|
||||||
|
createFiles(patchSupplementDir);
|
||||||
|
|
||||||
|
final releaseSnapshotDir = Directory.systemTemp.createTempSync();
|
||||||
|
final patchSnapshotDir = Directory.systemTemp.createTempSync();
|
||||||
|
apple.copySupplementFilesToSnapshotDirs(
|
||||||
|
releaseSupplementDir: releaseSupplementDir,
|
||||||
|
releaseSnapshotDir: releaseSnapshotDir,
|
||||||
|
patchSupplementDir: patchSupplementDir,
|
||||||
|
patchSnapshotDir: patchSnapshotDir,
|
||||||
|
);
|
||||||
|
expect(Directory(releaseSnapshotDir.path).listSync(), hasLength(2));
|
||||||
|
expect(Directory(patchSnapshotDir.path).listSync(), hasLength(2));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('ios', () {
|
group('ios', () {
|
||||||
final schemesPath = p.join(
|
final schemesPath = p.join(
|
||||||
'ios',
|
'ios',
|
||||||
|
|||||||
@@ -240,6 +240,24 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('iosSupplementDirectory', () {
|
||||||
|
test('returns correct path', () {
|
||||||
|
final tempDir = Directory.systemTemp.createTempSync();
|
||||||
|
File(p.join(tempDir.path, 'pubspec.yaml')).createSync(recursive: true);
|
||||||
|
Directory(
|
||||||
|
p.join(tempDir.path, 'build', 'ios', 'shorebird'),
|
||||||
|
).createSync(recursive: true);
|
||||||
|
final supplementDirectory = IOOverrides.runZoned(
|
||||||
|
() => runWithOverrides(() => shorebirdEnv.iosSupplementDirectory),
|
||||||
|
getCurrentDirectory: () => tempDir,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
supplementDirectory.path,
|
||||||
|
equals(p.join(tempDir.path, 'build', 'ios', 'shorebird')),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('macosPodfileLockFile', () {
|
group('macosPodfileLockFile', () {
|
||||||
test('returns correct path', () {
|
test('returns correct path', () {
|
||||||
final tempDir = Directory.systemTemp.createTempSync();
|
final tempDir = Directory.systemTemp.createTempSync();
|
||||||
|
|||||||
Reference in New Issue
Block a user