diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart index e40ee4fc3c6..d7d1fc109cc 100644 --- a/packages/flutter_tools/lib/src/asset.dart +++ b/packages/flutter_tools/lib/src/asset.dart @@ -272,6 +272,19 @@ class ManifestAssetBundle implements AssetBundle { final DevFSStringContent licenses = DevFSStringContent(licenseResult.combinedLicenses); additionalDependencies = licenseResult.dependencies; + if (wildcardDirectories.isNotEmpty) { + // Force the depfile to contain missing files so that Gradle does not skip + // the task. Wildcard directories are not compatible with full incremental + // builds. For more context see https://github.com/flutter/flutter/issues/56466 . + globals.printTrace( + 'Manifest contained wildcard assets. Inserting missing file into ' + 'build graph to force rerun. for more information see #56466.' + ); + final int suffix = Object().hashCode; + additionalDependencies.add( + globals.fs.file('DOES_NOT_EXIST_RERUN_FOR_WILDCARD$suffix').absolute); + } + _setIfChanged(_assetManifestJson, assetManifest); _setIfChanged(kFontManifestJson, fontManifest); _setIfChanged(_license, licenses); diff --git a/packages/flutter_tools/test/general.shard/asset_bundle_test.dart b/packages/flutter_tools/test/general.shard/asset_bundle_test.dart index 5f86a5809ac..a50127d524e 100644 --- a/packages/flutter_tools/test/general.shard/asset_bundle_test.dart +++ b/packages/flutter_tools/test/general.shard/asset_bundle_test.dart @@ -224,6 +224,83 @@ assets: ProcessManager: () => FakeProcessManager.any(), }); + testUsingContext('inserts dummy file into additionalDependencies when ' + 'wildcards are used', () async { + globals.fs.file('.packages').createSync(); + globals.fs.file(globals.fs.path.join('assets', 'bar.txt')).createSync(recursive: true); + globals.fs.file('pubspec.yaml') + ..createSync() + ..writeAsStringSync(r''' +name: example +flutter: + assets: + - assets/ +'''); + final AssetBundle bundle = AssetBundleFactory.instance.createBundle(); + + expect(await bundle.build(manifestPath: 'pubspec.yaml'), 0); + expect(bundle.additionalDependencies.single.path, contains('DOES_NOT_EXIST_RERUN_FOR_WILDCARD')); + }, overrides: { + FileSystem: () => MemoryFileSystem.test(), + ProcessManager: () => FakeProcessManager.any(), + }); + + testUsingContext('Does not insert dummy file into additionalDependencies ' + 'when wildcards are not used', () async { + globals.fs.file('.packages').createSync(); + globals.fs.file(globals.fs.path.join('assets', 'bar.txt')).createSync(recursive: true); + globals.fs.file('pubspec.yaml') + ..createSync() + ..writeAsStringSync(r''' +name: example +flutter: + assets: + - assets/bar.txt +'''); + final AssetBundle bundle = AssetBundleFactory.instance.createBundle(); + + expect(await bundle.build(manifestPath: 'pubspec.yaml'), 0); + expect(bundle.additionalDependencies, isEmpty); + }, overrides: { + FileSystem: () => MemoryFileSystem.test(), + ProcessManager: () => FakeProcessManager.any(), + }); + + testUsingContext('Does not insert dummy file into additionalDependencies ' + 'when wildcards are used by dependencies', () async { + globals.fs.file('.packages').writeAsStringSync(r''' +example:lib/ +foo:foo/lib/ +'''); + globals.fs.file(globals.fs.path.join('assets', 'foo', 'bar.txt')) + .createSync(recursive: true); + globals.fs.file('pubspec.yaml') + ..createSync() + ..writeAsStringSync(r''' +name: example +dependencies: + foo: any +'''); + globals.fs.file('foo/pubspec.yaml') + ..createSync(recursive: true) + ..writeAsStringSync(r''' +name: foo + +flutter: + assets: + - bar/ +'''); + final AssetBundle bundle = AssetBundleFactory.instance.createBundle(); + globals.fs.file('foo/bar/fizz.txt').createSync(recursive: true); + + expect(await bundle.build(manifestPath: 'pubspec.yaml'), 0); + expect(bundle.additionalDependencies, isEmpty); + }, overrides: { + FileSystem: () => MemoryFileSystem.test(), + ProcessManager: () => FakeProcessManager.any(), + Platform: () => FakePlatform(operatingSystem: 'linux'), + }); + testUsingContext('does not track wildcard directories from dependencies', () async { globals.fs.file('.packages').writeAsStringSync(r''' example:lib/