Scan assets from disk (#16413)
Scan folders when asset specified finishes with `/`
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index d2a38bf..b5514e5 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -9,6 +9,7 @@
import 'base/context.dart';
import 'base/file_system.dart';
+import 'base/platform.dart';
import 'build_info.dart';
import 'cache.dart';
import 'dart/package_map.dart';
@@ -365,9 +366,19 @@
return new DevFSStringContent(combinedLicenses);
}
+int _byBasename(_Asset a, _Asset b) {
+ return a.assetFile.basename.compareTo(b.assetFile.basename);
+}
+
DevFSContent _createAssetManifest(Map<_Asset, List<_Asset>> assetVariants) {
final Map<String, List<String>> jsonObject = <String, List<String>>{};
- for (_Asset main in assetVariants.keys) {
+
+ // necessary for making unit tests deterministic
+ final List<_Asset> sortedKeys = assetVariants
+ .keys.toList()
+ ..sort(_byBasename);
+
+ for (_Asset main in sortedKeys) {
final List<String> variants = <String>[];
for (_Asset variant in assetVariants[main])
variants.add(variant.entryUri.path);
@@ -485,6 +496,27 @@
/// map of assets to asset variants.
///
/// Returns null on missing assets.
+///
+/// Given package: 'test_package' and an assets directory like this:
+///
+/// assets/foo
+/// assets/var1/foo
+/// assets/var2/foo
+/// assets/bar
+///
+/// returns
+/// {
+/// asset: packages/test_package/assets/foo: [
+/// asset: packages/test_package/assets/foo,
+/// asset: packages/test_package/assets/var1/foo,
+/// asset: packages/test_package/assets/var2/foo,
+/// ],
+/// asset: packages/test_package/assets/bar: [
+/// asset: packages/test_package/assets/bar,
+/// ],
+/// }
+///
+
Map<_Asset, List<_Asset>> _parseAssets(
PackageMap packageMap,
FlutterManifest flutterManifest,
@@ -496,27 +528,15 @@
final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs);
for (Uri assetUri in flutterManifest.assets) {
- final _Asset asset = _resolveAsset(
- packageMap,
- assetBase,
- assetUri,
- packageName,
- );
- final List<_Asset> variants = <_Asset>[];
- for (String path in cache.variantsFor(asset.assetFile.path)) {
- final String relativePath = fs.path.relative(path, from: asset.baseDir);
- final Uri relativeUri = fs.path.toUri(relativePath);
- final Uri entryUri = asset.symbolicPrefixUri == null
- ? relativeUri
- : asset.symbolicPrefixUri.resolveUri(relativeUri);
- variants.add(new _Asset(
- baseDir: asset.baseDir,
- entryUri: entryUri,
- relativeUri: relativeUri,
- ));
+ if (assetUri.toString().endsWith('/')) {
+ _parseAssetsFromFolder(packageMap, flutterManifest, assetBase,
+ cache, result, assetUri,
+ excludeDirs: excludeDirs, packageName: packageName);
+ } else {
+ _parseAssetFromFile(packageMap, flutterManifest, assetBase,
+ cache, result, assetUri,
+ excludeDirs: excludeDirs, packageName: packageName);
}
-
- result[asset] = variants;
}
// Add assets referenced in the fonts section of the manifest.
@@ -540,6 +560,72 @@
return result;
}
+void _parseAssetsFromFolder(PackageMap packageMap,
+ FlutterManifest flutterManifest,
+ String assetBase,
+ _AssetDirectoryCache cache,
+ Map<_Asset, List<_Asset>> result,
+ Uri assetUri, {
+ List<String> excludeDirs: const <String>[],
+ String packageName
+}) {
+ final String directoryPath = fs.path.join(
+ assetBase, assetUri.toFilePath(windows: platform.isWindows));
+
+ if (!fs.directory(directoryPath).existsSync()) {
+ printError('Error: unable to find directory entry in pubspec.yaml: $directoryPath');
+ return;
+ }
+
+ final List<FileSystemEntity> lister = fs.directory(directoryPath).listSync();
+
+ for (FileSystemEntity entity in lister) {
+ if (entity is File) {
+ final String relativePath = fs.path.relative(entity.path, from: assetBase);
+
+ final Uri uri = new Uri.file(relativePath, windows: platform.isWindows);
+
+ _parseAssetFromFile(packageMap, flutterManifest, assetBase, cache, result,
+ uri, packageName: packageName);
+ }
+ }
+}
+
+void _parseAssetFromFile(PackageMap packageMap,
+ FlutterManifest flutterManifest,
+ String assetBase,
+ _AssetDirectoryCache cache,
+ Map<_Asset, List<_Asset>> result,
+ Uri assetUri, {
+ List<String> excludeDirs: const <String>[],
+ String packageName
+}) {
+ final _Asset asset = _resolveAsset(
+ packageMap,
+ assetBase,
+ assetUri,
+ packageName,
+ );
+ final List<_Asset> variants = <_Asset>[];
+ for (String path in cache.variantsFor(asset.assetFile.path)) {
+ final String relativePath = fs.path.relative(path, from: asset.baseDir);
+ final Uri relativeUri = fs.path.toUri(relativePath);
+ final Uri entryUri = asset.symbolicPrefixUri == null
+ ? relativeUri
+ : asset.symbolicPrefixUri.resolveUri(relativeUri);
+
+ variants.add(
+ new _Asset(
+ baseDir: asset.baseDir,
+ entryUri: entryUri,
+ relativeUri: relativeUri,
+ )
+ );
+ }
+
+ result[asset] = variants;
+}
+
_Asset _resolveAsset(
PackageMap packageMap,
String assetsBaseDir,
diff --git a/packages/flutter_tools/lib/src/dart/package_map.dart b/packages/flutter_tools/lib/src/dart/package_map.dart
index dd04a11..c1b7bfc 100644
--- a/packages/flutter_tools/lib/src/dart/package_map.dart
+++ b/packages/flutter_tools/lib/src/dart/package_map.dart
@@ -5,12 +5,14 @@
import 'package:package_config/packages_file.dart' as packages_file;
import '../base/file_system.dart';
+import '../base/platform.dart';
const String kPackagesFileName = '.packages';
Map<String, Uri> _parse(String packagesPath) {
final List<int> source = fs.file(packagesPath).readAsBytesSync();
- return packages_file.parse(source, new Uri.file(packagesPath));
+ return packages_file.parse(source,
+ new Uri.file(packagesPath, windows: platform.isWindows));
}
class PackageMap {
diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart
index 1731ceb..0c26c47 100644
--- a/packages/flutter_tools/lib/src/flutter_manifest.dart
+++ b/packages/flutter_tools/lib/src/flutter_manifest.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:convert' as convert;
import 'package:json_schema/json_schema.dart';
import 'package:meta/meta.dart';
@@ -151,13 +152,27 @@
String toString() => '$runtimeType(asset: ${assetUri.path}, weight; $weight, style: $style)';
}
-Future<bool> _validate(Object manifest) async {
- final String schemaPath = fs.path.join(
+@visibleForTesting
+String buildSchemaDir(FileSystem fs) {
+ return fs.path.join(
fs.path.absolute(Cache.flutterRoot), 'packages', 'flutter_tools', 'schema',
+ );
+}
+
+@visibleForTesting
+String buildSchemaPath(FileSystem fs) {
+ return fs.path.join(
+ buildSchemaDir(fs),
'pubspec_yaml.json',
);
- final Schema schema = await Schema.createSchemaFromUrl(fs.path.toUri(schemaPath).toString());
+}
+Future<bool> _validate(Object manifest) async {
+ final String schemaPath = buildSchemaPath(fs);
+
+ final String schemaData = fs.file(schemaPath).readAsStringSync();
+ final Schema schema = await Schema.createSchema(
+ convert.json.decode(schemaData));
final Validator validator = new Validator(schema);
if (validator.validate(manifest)) {
return true;