Commit 0b95e9c2 authored by Sarah Zakarias's avatar Sarah Zakarias Committed by GitHub

Support transitive asset dependency (#12032)

parent a1f03977
...@@ -137,7 +137,7 @@ class AssetBundle { ...@@ -137,7 +137,7 @@ class AssetBundle {
packageMap, packageMap,
packageManifestDescriptor['flutter'], packageManifestDescriptor['flutter'],
packageBasePath, packageBasePath,
packageKey: packageName, packageName: packageName,
)); ));
} }
} }
...@@ -434,7 +434,7 @@ Map<_Asset, List<_Asset>> _parseAssets( ...@@ -434,7 +434,7 @@ Map<_Asset, List<_Asset>> _parseAssets(
Map<String, dynamic> manifestDescriptor, Map<String, dynamic> manifestDescriptor,
String assetBase, { String assetBase, {
List<String> excludeDirs: const <String>[], List<String> excludeDirs: const <String>[],
String packageKey String packageName
}) { }) {
final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{}; final Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{};
...@@ -444,11 +444,13 @@ Map<_Asset, List<_Asset>> _parseAssets( ...@@ -444,11 +444,13 @@ Map<_Asset, List<_Asset>> _parseAssets(
if (manifestDescriptor.containsKey('assets')) { if (manifestDescriptor.containsKey('assets')) {
final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs); final _AssetDirectoryCache cache = new _AssetDirectoryCache(excludeDirs);
for (String assetName in manifestDescriptor['assets']) { for (String assetName in manifestDescriptor['assets']) {
final _Asset asset = packageKey != null final _Asset asset = _resolveAsset(
? _resolvePackageAsset(assetBase, packageKey, assetName) packageMap,
: _resolveAsset(packageMap, assetBase, assetName); assetBase,
assetName,
packageName,
);
final List<_Asset> variants = <_Asset>[]; final List<_Asset> variants = <_Asset>[];
for (String path in cache.variantsFor(asset.assetFile.path)) { for (String path in cache.variantsFor(asset.assetFile.path)) {
final String key = fs.path.relative(path, from: asset.base); final String key = fs.path.relative(path, from: asset.base);
String assetEntry; String assetEntry;
...@@ -473,7 +475,12 @@ Map<_Asset, List<_Asset>> _parseAssets( ...@@ -473,7 +475,12 @@ Map<_Asset, List<_Asset>> _parseAssets(
if (asset == null) if (asset == null)
continue; continue;
final _Asset baseAsset = _resolveAsset(packageMap, assetBase, asset); final _Asset baseAsset = _resolveAsset(
packageMap,
assetBase,
asset,
packageName
);
if (!baseAsset.assetFileExists) { if (!baseAsset.assetFileExists) {
printError('Error: unable to locate asset entry in pubspec.yaml: "$asset".'); printError('Error: unable to locate asset entry in pubspec.yaml: "$asset".');
return null; return null;
...@@ -487,42 +494,46 @@ Map<_Asset, List<_Asset>> _parseAssets( ...@@ -487,42 +494,46 @@ Map<_Asset, List<_Asset>> _parseAssets(
return result; return result;
} }
_Asset _resolvePackageAsset(
String assetBase,
String packageName,
String asset,
) {
return new _Asset(
base: assetBase,
assetEntry: 'packages/$packageName/$asset',
relativePath: asset,
);
}
_Asset _resolveAsset( _Asset _resolveAsset(
PackageMap packageMap, PackageMap packageMap,
String assetBase, String assetBase,
String asset, String asset,
String packageName,
) { ) {
if (asset.startsWith('packages/') && !fs.isFileSync(fs.path.join(assetBase, asset))) { if (asset.startsWith('packages/') && !fs.isFileSync(fs.path.join(assetBase, asset))) {
// Convert packages/flutter_gallery_assets/clouds-0.png to clouds-0.png. // The asset is referenced in the pubspec.yaml as
String packageKey = asset.substring(9); // 'packages/PACKAGE_NAME/PATH/TO/ASSET
String relativeAsset = asset; final _Asset packageAsset = _resolvePackageAsset(asset, packageMap);
if (packageAsset != null)
final int index = packageKey.indexOf('/'); return packageAsset;
if (index != -1) { }
relativeAsset = packageKey.substring(index + 1);
packageKey = packageKey.substring(0, index);
}
final Uri uri = packageMap.map[packageKey]; final String assetEntry = packageName != null
if (uri != null && uri.scheme == 'file') { ? 'packages/$packageName/$asset' // Asset from, and declared in $packageName
final File file = fs.file(uri); : null; // Asset from the current application
return new _Asset(base: file.path, assetEntry: asset, relativePath: relativeAsset); return new _Asset(base: assetBase, assetEntry: assetEntry, relativePath: asset);
} }
_Asset _resolvePackageAsset(String asset, PackageMap packageMap) {
assert(asset.startsWith('packages/'));
String packageKey = asset.substring(9);
String relativeAsset = asset;
final int index = packageKey.indexOf('/');
if (index != -1) {
relativeAsset = packageKey.substring(index + 1);
packageKey = packageKey.substring(0, index);
} }
return new _Asset(base: assetBase, relativePath: asset); final Uri uri = packageMap.map[packageKey];
if (uri != null && uri.scheme == 'file') {
final File file = fs.file(uri);
final String base = file.path.substring(0, file.path.length - 1);
return new _Asset(base: base, assetEntry: asset, relativePath: relativeAsset);
}
printStatus('Error detected in pubspec.yaml:', emphasis: true);
printError('Could not resolve $packageKey for asset $asset.\n');
return null;
} }
dynamic _loadFlutterManifest(String manifestPath) { dynamic _loadFlutterManifest(String manifestPath) {
......
...@@ -133,6 +133,32 @@ $assetsSection ...@@ -133,6 +133,32 @@ $assetsSection
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(), FileSystem: () => new MemoryFileSystem(),
}); });
testUsingContext('One package with one asset not specified', () async {
establishFlutterRoot();
final List<String> assetEntries = <String>['packages/test_package/a/foo'];
writePubspecFile(
'pubspec.yaml',
'test',
assets: assetEntries,
);
writePackagesFile('test_package:p/p/lib/');
writePubspecFile('p/p/pubspec.yaml', 'test_package');
final List<String> assets = <String>['a/foo'];
writeAssets('p/p/lib/', assets);
final String expectedAssetManifest = '{"packages/test_package/a/foo":'
'["packages/test_package/a/foo"]}';
await buildAndVerifyAssets(
assets,
<String>['test_package'],
expectedAssetManifest,
);
}, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(),
});
testUsingContext('One package with asset variants', () async { testUsingContext('One package with asset variants', () async {
establishFlutterRoot(); establishFlutterRoot();
...@@ -160,6 +186,35 @@ $assetsSection ...@@ -160,6 +186,35 @@ $assetsSection
FileSystem: () => new MemoryFileSystem(), FileSystem: () => new MemoryFileSystem(),
}); });
testUsingContext('One package with asset variants not specified', () async {
establishFlutterRoot();
writePubspecFile(
'pubspec.yaml',
'test',
assets: <String>['packages/test_package/a/foo'],
);
writePackagesFile('test_package:p/p/lib/');
writePubspecFile(
'p/p/pubspec.yaml',
'test_package',
);
final List<String> assets = <String>['a/foo', 'a/v/foo'];
writeAssets('p/p/lib/', assets);
final String expectedManifest = '{"packages/test_package/a/foo":'
'["packages/test_package/a/foo","packages/test_package/a/v/foo"]}';
await buildAndVerifyAssets(
assets,
<String>['test_package'],
expectedManifest,
);
}, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(),
});
testUsingContext('One package with two assets', () async { testUsingContext('One package with two assets', () async {
establishFlutterRoot(); establishFlutterRoot();
...@@ -187,10 +242,47 @@ $assetsSection ...@@ -187,10 +242,47 @@ $assetsSection
FileSystem: () => new MemoryFileSystem(), FileSystem: () => new MemoryFileSystem(),
}); });
testUsingContext('One package with two assets not specified', () async {
establishFlutterRoot();
final List<String> assetEntries = <String>[
'packages/test_package/a/foo',
'packages/test_package/a/bar',
];
writePubspecFile(
'pubspec.yaml',
'test',
assets: assetEntries,
);
writePackagesFile('test_package:p/p/lib/');
final List<String> assets = <String>['a/foo', 'a/bar'];
writePubspecFile(
'p/p/pubspec.yaml',
'test_package',
);
writeAssets('p/p/lib/', assets);
final String expectedAssetManifest =
'{"packages/test_package/a/foo":["packages/test_package/a/foo"],'
'"packages/test_package/a/bar":["packages/test_package/a/bar"]}';
await buildAndVerifyAssets(
assets,
<String>['test_package'],
expectedAssetManifest,
);
}, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(),
});
testUsingContext('Two packages with assets', () async { testUsingContext('Two packages with assets', () async {
establishFlutterRoot(); establishFlutterRoot();
writePubspecFile('pubspec.yaml', 'test'); writePubspecFile(
'pubspec.yaml',
'test',
);
writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/'); writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
writePubspecFile( writePubspecFile(
'p/p/pubspec.yaml', 'p/p/pubspec.yaml',
...@@ -221,5 +313,79 @@ $assetsSection ...@@ -221,5 +313,79 @@ $assetsSection
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(), FileSystem: () => new MemoryFileSystem(),
}); });
testUsingContext('Two packages with assets not specified', () async {
establishFlutterRoot();
final List<String> assetEntries = <String>[
'packages/test_package/a/foo',
'packages/test_package2/a/foo',
];
writePubspecFile(
'pubspec.yaml',
'test',
assets: assetEntries,
);
writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
writePubspecFile(
'p/p/pubspec.yaml',
'test_package',
);
writePubspecFile(
'p2/p/pubspec.yaml',
'test_package2',
);
final List<String> assets = <String>['a/foo', 'a/v/foo'];
writeAssets('p/p/lib/', assets);
writeAssets('p2/p/lib/', assets);
final String expectedAssetManifest =
'{"packages/test_package/a/foo":'
'["packages/test_package/a/foo","packages/test_package/a/v/foo"],'
'"packages/test_package2/a/foo":'
'["packages/test_package2/a/foo","packages/test_package2/a/v/foo"]}';
await buildAndVerifyAssets(
assets,
<String>['test_package', 'test_package2'],
expectedAssetManifest,
);
}, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(),
});
testUsingContext('Transitive asset dependency', () async {
establishFlutterRoot();
writePubspecFile(
'pubspec.yaml',
'test',
);
writePackagesFile('test_package:p/p/lib/\ntest_package2:p2/p/lib/');
writePubspecFile(
'p/p/pubspec.yaml',
'test_package',
assets: <String>['packages/test_package2/a/foo']
);
writePubspecFile(
'p2/p/pubspec.yaml',
'test_package2',
);
final List<String> assets = <String>['a/foo', 'a/v/foo'];
writeAssets('p2/p/lib/', assets);
final String expectedAssetManifest =
'{"packages/test_package2/a/foo":'
'["packages/test_package2/a/foo","packages/test_package2/a/v/foo"]}';
await buildAndVerifyAssets(
assets,
<String>['test_package2'],
expectedAssetManifest,
);
}, overrides: <Type, Generator>{
FileSystem: () => new MemoryFileSystem(),
});
}); });
} }
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