Commit edc548ad authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Update the license mechanism to show package names (#5051)

parent a555ee47
......@@ -44,10 +44,12 @@ abstract class LicenseEntry {
/// const constructors so that they can be used in const expressions.
const LicenseEntry();
/// Returns each paragraph of the license as a [LicenseParagraph], which
/// consists of a string and some formatting information. Paragraphs can
/// include newline characters, but this is discouraged as it results in
/// ugliness.
/// The names of the packages that this license entry applies to.
Iterable<String> get packages;
/// The paragraphs of the license, each as a [LicenseParagraph] consisting of
/// a string and some formatting information. Paragraphs can include newline
/// characters, but this is discouraged as it results in ugliness.
Iterable<LicenseParagraph> get paragraphs;
}
......@@ -65,7 +67,7 @@ enum _LicenseEntryWithLineBreaksParserState {
///
/// ```dart
/// LicenseRegistry.addLicense(() {
/// yield new LicenseEntryWithLineBreaks('''
/// yield new LicenseEntryWithLineBreaks(<String>['my_library'], '''
/// Copyright 2016 The Sample Authors. All rights reserved.
///
/// Redistribution and use in source and binary forms, with or without
......@@ -102,7 +104,10 @@ class LicenseEntryWithLineBreaks extends LicenseEntry {
/// Create a license entry for a license whose text is hard-wrapped within
/// paragraphs and has paragraph breaks denoted by blank lines or with
/// indented text.
const LicenseEntryWithLineBreaks(this.text);
const LicenseEntryWithLineBreaks(this.packages, this.text);
@override
final List<String> packages;
/// The text of the license.
///
......
......@@ -355,7 +355,6 @@ class _LicensePageState extends State<LicensePage> {
Future<Null> _initLicenses() async {
await for (LicenseEntry license in LicenseRegistry.licenses) {
bool haveMargin = true;
setState(() {
_licenses.add(new Padding(
padding: new EdgeInsets.symmetric(vertical: 18.0),
......@@ -364,10 +363,20 @@ class _LicensePageState extends State<LicensePage> {
textAlign: TextAlign.center
)
));
_licenses.add(new Container(
decoration: new BoxDecoration(
border: new Border(bottom: new BorderSide(width: 0.0))
),
child: new Text(
license.packages.join(', '),
style: new TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center
)
));
for (LicenseParagraph paragraph in license.paragraphs) {
if (paragraph.indent == LicenseParagraph.centeredIndent) {
_licenses.add(new Padding(
padding: new EdgeInsets.only(top: haveMargin ? 0.0 : 16.0),
padding: new EdgeInsets.only(top: 16.0),
child: new Text(
paragraph.text,
style: new TextStyle(fontWeight: FontWeight.bold),
......@@ -377,11 +386,10 @@ class _LicensePageState extends State<LicensePage> {
} else {
assert(paragraph.indent >= 0);
_licenses.add(new Padding(
padding: new EdgeInsets.only(top: haveMargin ? 0.0 : 8.0, left: 16.0 * paragraph.indent),
padding: new EdgeInsets.only(top: 8.0, left: 16.0 * paragraph.indent),
child: new Text(paragraph.text)
));
}
haveMargin = false;
}
});
}
......
......@@ -35,7 +35,16 @@ abstract class ServicesBinding extends BindingBase {
Stream<LicenseEntry> _addLicenses() async* {
final String rawLicenses = await rootBundle.loadString('LICENSE', cache: false);
final List<String> licenses = rawLicenses.split(_licenseSeparator);
for (String license in licenses)
yield new LicenseEntryWithLineBreaks(license);
for (String license in licenses) {
final int split = license.indexOf('\n\n');
if (split >= 0) {
yield new LicenseEntryWithLineBreaks(
license.substring(0, split).split('\n'),
license.substring(split + 2)
);
} else {
yield new LicenseEntryWithLineBreaks(const <String>[], license);
}
}
}
}
......@@ -9,7 +9,7 @@ void main() {
test('LicenseEntryWithLineBreaks - most cases', () {
// There's some trailing spaces in this string.
// To avoid IDEs stripping them, I've escaped them as \u0020.
List<LicenseParagraph> paragraphs = new LicenseEntryWithLineBreaks('''
List<LicenseParagraph> paragraphs = new LicenseEntryWithLineBreaks(null, '''
A
A
A
......@@ -157,16 +157,16 @@ S
});
test('LicenseEntryWithLineBreaks - leading and trailing whitespace', () {
expect(new LicenseEntryWithLineBreaks(' \n\n ').paragraphs.toList(), isEmpty);
expect(new LicenseEntryWithLineBreaks(null, ' \n\n ').paragraphs.toList(), isEmpty);
List<LicenseParagraph> paragraphs;
paragraphs = new LicenseEntryWithLineBreaks(' \nA\n ').paragraphs.toList();
paragraphs = new LicenseEntryWithLineBreaks(null, ' \nA\n ').paragraphs.toList();
expect(paragraphs[0].text, 'A');
expect(paragraphs[0].indent, 0);
expect(paragraphs, hasLength(1));
paragraphs = new LicenseEntryWithLineBreaks('\n\n\nA\n\n\n').paragraphs.toList();
paragraphs = new LicenseEntryWithLineBreaks(null, '\n\n\nA\n\n\n').paragraphs.toList();
expect(paragraphs[0].text, 'A');
expect(paragraphs[0].indent, 0);
expect(paragraphs, hasLength(1));
......@@ -175,12 +175,12 @@ S
test('LicenseRegistry', () async {
expect(await LicenseRegistry.licenses.toList(), isEmpty);
LicenseRegistry.addLicense(() async* {
yield new LicenseEntryWithLineBreaks('A');
yield new LicenseEntryWithLineBreaks('B');
yield new LicenseEntryWithLineBreaks(null, 'A');
yield new LicenseEntryWithLineBreaks(null, 'B');
});
LicenseRegistry.addLicense(() async* {
yield new LicenseEntryWithLineBreaks('C');
yield new LicenseEntryWithLineBreaks('D');
yield new LicenseEntryWithLineBreaks(null, 'C');
yield new LicenseEntryWithLineBreaks(null, 'D');
});
expect(await LicenseRegistry.licenses.toList(), hasLength(4));
List<LicenseEntry> licenses = await LicenseRegistry.licenses.toList();
......
......@@ -203,24 +203,51 @@ Map<_Asset, List<_Asset>> _parseAssets(
final String _licenseSeparator = '\n' + ('-' * 80) + '\n';
/// Returns a ZipEntry representing the license file.
ZipEntry _obtainLicenses(
Future<ZipEntry> _obtainLicenses(
PackageMap packageMap,
String assetBase
) {
) async {
// Read the LICENSE file from each package in the .packages file,
// splitting each one into each component license (so that we can
// de-dupe if possible).
final Set<String> packageLicenses = new Set<String>();
final Iterable<Uri> packages = packageMap.map.values;
for (Uri package in packages) {
// For the sky_engine package we assume each license starts with
// package names. For the other packages we assume that each
// license is raw.
final Map<String, Set<String>> packageLicenses = <String, Set<String>>{};
for (String packageName in packageMap.map.keys) {
final Uri package = packageMap.map[packageName];
if (package != null && package.scheme == 'file') {
final File file = new File.fromUri(package.resolve('../LICENSE'));
if (file.existsSync())
packageLicenses.addAll(file.readAsStringSync().split(_licenseSeparator));
if (file.existsSync()) {
final List<String> rawLicenses = (await file.readAsString()).split(_licenseSeparator);
for (String rawLicense in rawLicenses) {
String licenseText;
List<String> packageNames;
if (packageName == 'sky_engine') {
final int split = rawLicense.indexOf('\n\n');
if (split >= 0) {
packageNames = rawLicense.substring(0, split).split('\n');
licenseText = rawLicense.substring(split + 2);
}
}
if (licenseText == null) {
licenseText = rawLicense;
packageNames = <String>[packageName];
}
packageLicenses.putIfAbsent(rawLicense, () => new Set<String>())
..addAll(packageNames);
}
}
}
}
final List<String> combinedLicensesList = packageLicenses.toList();
final List<String> combinedLicensesList = packageLicenses.keys.map(
(String license) {
List<String> packageNames = packageLicenses[license].toList()
..sort();
return packageNames.join('\n') + '\n\n' + license;
}
).toList();
combinedLicensesList.sort();
final String combinedLicenses = combinedLicensesList.join(_licenseSeparator);
......@@ -464,7 +491,8 @@ Future<int> assemble({
if (fontManifest != null)
zipBuilder.addEntry(fontManifest);
zipBuilder.addEntry(_obtainLicenses(packageMap, assetBasePath));
// TODO(ianh): Only do the following line if we've changed packages
zipBuilder.addEntry(await _obtainLicenses(packageMap, assetBasePath));
ensureDirectoryExists(outputPath);
......
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