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