Skip to content

Commit 3af7f9b

Browse files
authored
fix(flutter_tools): findBundleFile w/multiple flavor dimensions (#127133)
Fixes the `findBundleFile` method in `gradle.dart` to correctly locate app bundles generated from multiple flavor dimensions. - closes flutter/flutter#92316 - closes flutter/flutter#65264
1 parent 0d67c7e commit 3af7f9b

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed

packages/flutter_tools/lib/src/android/gradle.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,22 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
983983
fileCandidates.add(getBundleDirectory(project)
984984
.childDirectory('${buildInfo.uncapitalizedFlavor}${camelCase('_${buildInfo.modeName}')}')
985985
.childFile('app-${buildInfo.uncapitalizedFlavor}-${buildInfo.modeName}.aab'));
986+
987+
// The Android Gradle plugin uses kebab-case and lowercases the first character of the flavor name
988+
// when multiple flavor dimensions are used:
989+
// e.g.
990+
// flavorDimensions "dimension1","dimension2"
991+
// productFlavors {
992+
// foo {
993+
// dimension "dimension1"
994+
// }
995+
// bar {
996+
// dimension "dimension2"
997+
// }
998+
// }
999+
fileCandidates.add(getBundleDirectory(project)
1000+
.childDirectory('${buildInfo.uncapitalizedFlavor}${camelCase('_${buildInfo.modeName}')}')
1001+
.childFile('app-${kebabCase(buildInfo.uncapitalizedFlavor!)}-${buildInfo.modeName}.aab'));
9861002
}
9871003
for (final File bundleFile in fileCandidates) {
9881004
if (bundleFile.existsSync()) {

packages/flutter_tools/lib/src/base/utils.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ String camelCase(String str) {
2626
return str;
2727
}
2828

29+
/// Convert `fooBar` to `foo-bar`.
30+
String kebabCase(String str) {
31+
return snakeCase(str, '-');
32+
}
33+
2934
final RegExp _upperRegex = RegExp(r'[A-Z]');
3035

3136
/// Convert `fooBar` to `foo_bar`.

packages/flutter_tools/test/general.shard/android/gradle_find_bundle_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ void main() {
1919
fileSystem = MemoryFileSystem.test();
2020
});
2121

22+
testWithoutContext('Finds app bundle when flavor contains multiple dimensions in release mode', () {
23+
final FlutterProject project = generateFakeAppBundle('fooBarRelease', 'app-foo-bar-release.aab', fileSystem);
24+
final File bundle = findBundleFile(
25+
project,
26+
const BuildInfo(BuildMode.release, 'fooBar', treeShakeIcons: false),
27+
BufferLogger.test(),
28+
TestUsage(),
29+
);
30+
31+
expect(bundle, isNotNull);
32+
expect(bundle.path, '/build/app/outputs/bundle/fooBarRelease/app-foo-bar-release.aab');
33+
});
34+
2235
testWithoutContext('Finds app bundle when flavor contains underscores in release mode', () {
2336
final FlutterProject project = generateFakeAppBundle('foo_barRelease', 'app.aab', fileSystem);
2437
final File bundle = findBundleFile(
@@ -84,6 +97,19 @@ void main() {
8497
expect(bundle.path, '/build/app/outputs/bundle/release/app.aab');
8598
});
8699

100+
testWithoutContext('Finds app bundle when flavor contains multiple dimensions in debug mode', () {
101+
final FlutterProject project = generateFakeAppBundle('fooBarDebug', 'app-foo-bar-debug.aab', fileSystem);
102+
final File bundle = findBundleFile(
103+
project,
104+
const BuildInfo(BuildMode.debug, 'fooBar', treeShakeIcons: false),
105+
BufferLogger.test(),
106+
TestUsage(),
107+
);
108+
109+
expect(bundle, isNotNull);
110+
expect(bundle.path, '/build/app/outputs/bundle/fooBarDebug/app-foo-bar-debug.aab');
111+
});
112+
87113
testWithoutContext('Finds app bundle when flavor contains underscores in debug mode', () {
88114
final FlutterProject project = generateFakeAppBundle('foo_barDebug', 'app.aab', fileSystem);
89115
final File bundle = findBundleFile(
@@ -149,6 +175,19 @@ void main() {
149175
expect(bundle.path, '/build/app/outputs/bundle/debug/app.aab');
150176
});
151177

178+
testWithoutContext('Finds app bundle when flavor contains multiple dimensions in profile mode', () {
179+
final FlutterProject project = generateFakeAppBundle('fooBarProfile', 'app-foo-bar-profile.aab', fileSystem);
180+
final File bundle = findBundleFile(
181+
project,
182+
const BuildInfo(BuildMode.profile, 'fooBar', treeShakeIcons: false),
183+
BufferLogger.test(),
184+
TestUsage(),
185+
);
186+
187+
expect(bundle, isNotNull);
188+
expect(bundle.path, '/build/app/outputs/bundle/fooBarProfile/app-foo-bar-profile.aab');
189+
});
190+
152191
testWithoutContext('Finds app bundle when flavor contains underscores in profile mode', () {
153192
final FlutterProject project = generateFakeAppBundle('foo_barProfile', 'app.aab', fileSystem);
154193
final File bundle = findBundleFile(

packages/flutter_tools/test/general.shard/utils_test.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,17 @@ baz=qux
120120
expect(snakeCase('ABC'), equals('a_b_c'));
121121
});
122122

123+
testWithoutContext('kebabCase', () async {
124+
expect(kebabCase('abc'), equals('abc'));
125+
expect(kebabCase('abC'), equals('ab-c'));
126+
expect(kebabCase('aBc'), equals('a-bc'));
127+
expect(kebabCase('aBC'), equals('a-b-c'));
128+
expect(kebabCase('Abc'), equals('abc'));
129+
expect(kebabCase('AbC'), equals('ab-c'));
130+
expect(kebabCase('ABc'), equals('a-bc'));
131+
expect(kebabCase('ABC'), equals('a-b-c'));
132+
});
133+
123134
testWithoutContext('sentenceCase', () async {
124135
expect(sentenceCase('abc'), equals('Abc'));
125136
expect(sentenceCase('ab_c'), equals('Ab_c'));

0 commit comments

Comments
 (0)