diff --git a/lib/src/validator.dart b/lib/src/validator.dart index dea568fd5300fea86b3537cf7e78c96b48cb7680..3e491a93a3954bc935116af4c4ded23c436ebb43 100644 --- a/lib/src/validator.dart +++ b/lib/src/validator.dart @@ -9,6 +9,7 @@ import 'log.dart' as log; import 'io.dart'; import 'system_cache.dart'; import 'utils.dart'; +import 'validator/lib.dart'; import 'validator/license.dart'; import 'validator/name.dart'; import 'validator/pubspec_field.dart'; @@ -40,6 +41,7 @@ abstract class Validator { static Future<Pair<List<String>, List<String>>> runAll( Entrypoint entrypoint) { var validators = [ + new LibValidator(entrypoint), new LicenseValidator(entrypoint), new NameValidator(entrypoint), new PubspecFieldValidator(entrypoint) diff --git a/lib/src/validator/lib.dart b/lib/src/validator/lib.dart new file mode 100644 index 0000000000000000000000000000000000000000..64f44c6365f5694c8468c8b73d513a0a171a7416 --- /dev/null +++ b/lib/src/validator/lib.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library lib_validator; + +import 'dart:io'; + +import '../entrypoint.dart'; +import '../io.dart'; +import '../system_cache.dart'; +import '../utils.dart'; +import '../validator.dart'; + +// TODO(nweiz): When issue 7196 is fixed, complain about non-Dart files in lib. +/// A validator that checks that libraries in "lib/" (and not "lib/src/") exist +/// and are well-formed. +class LibValidator extends Validator { + LibValidator(Entrypoint entrypoint) + : super(entrypoint); + + Future validate() { + var libDir = join(entrypoint.root.dir, "lib"); + return dirExists(libDir).chain((libDirExists) { + if (!libDirExists) { + errors.add('Your package must have a "lib/" directory so users have ' + 'something to import.'); + return new Future.immediate(null); + } + + return listDir(libDir).transform((files) { + files = files.map((file) => relativeTo(file, libDir)); + if (files.isEmpty) { + errors.add('The "lib/" directory may not be empty so users have ' + 'something to import'); + } else if (files.length == 1 && files.first == "src") { + errors.add('The "lib/" directory must contain something other than ' + '"src/" so users have something to import'); + } + }); + }); + } +} diff --git a/test/oauth2_test.dart b/test/oauth2_test.dart index fdbf92bd341d2378e11dd2be7be2065890d718a0..32e4a75a729b647d628df36057dccc226a2699a5 100644 --- a/test/oauth2_test.dart +++ b/test/oauth2_test.dart @@ -15,12 +15,7 @@ import '../../pub/io.dart'; import '../../pub/utils.dart'; main() { - setUp(() { - dir(appPath, [ - libPubspec("test_pkg", "1.0.0"), - file("LICENSE", "Eh, do what you want.") - ]).scheduleCreate(); - }); + setUp(() => normalPackage.scheduleCreate()); test('with no credentials.json, authenticates and saves credentials.json', () { diff --git a/test/pub_lish_test.dart b/test/pub_lish_test.dart index 58f6a1983ed7f4008f9c3206de1d791237a669b4..a947601d772229b92df61feea78b226ddf001fcb 100644 --- a/test/pub_lish_test.dart +++ b/test/pub_lish_test.dart @@ -47,12 +47,7 @@ void handleUpload(ScheduledServer server) { } main() { - setUp(() { - dir(appPath, [ - libPubspec("test_pkg", "1.0.0"), - file("LICENSE", "Eh, do what you want.") - ]).scheduleCreate(); - }); + setUp(() => normalPackage.scheduleCreate()); test('archives and uploads a package', () { var server = new ScheduledServer(); diff --git a/test/test_pub.dart b/test/test_pub.dart index 806ce3ee34d0a5a6cb5f46083b7e467d105ef267..aa8e8797bdfb22776be4e989e8ee260b518b0744 100644 --- a/test/test_pub.dart +++ b/test/test_pub.dart @@ -222,6 +222,15 @@ void servePackages(List<Map> pubspecs) { /** Converts [value] into a YAML string. */ String yaml(value) => JSON.stringify(value); +/// Describes a package that passes all validation. +Descriptor get normalPackage => dir(appPath, [ + libPubspec("test_pkg", "1.0.0"), + file("LICENSE", "Eh, do what you want."), + dir("lib", [ + file("test_pkg.dart", "int i = 1;") + ]) +]); + /** * Describes a file named `pubspec.yaml` with the given YAML-serialized * [contents], which should be a serializable object. diff --git a/test/validator_test.dart b/test/validator_test.dart index e5005bfb9627f7dccfef0c127c0cec3cad8b905b..d9877eb45de9c678b220df0939f5f386b3590d78 100644 --- a/test/validator_test.dart +++ b/test/validator_test.dart @@ -12,6 +12,7 @@ import '../../../pkg/unittest/lib/unittest.dart'; import '../../pub/entrypoint.dart'; import '../../pub/io.dart'; import '../../pub/validator.dart'; +import '../../pub/validator/lib.dart'; import '../../pub/validator/license.dart'; import '../../pub/validator/name.dart'; import '../../pub/validator/pubspec_field.dart'; @@ -28,19 +29,16 @@ void expectValidationWarning(ValidatorCreator fn) { expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isNot(isEmpty))); } -Validator pubspecField(Entrypoint entrypoint) => - new PubspecFieldValidator(entrypoint); +Validator lib(Entrypoint entrypoint) => new LibValidator(entrypoint); Validator license(Entrypoint entrypoint) => new LicenseValidator(entrypoint); Validator name(Entrypoint entrypoint) => new NameValidator(entrypoint); -void scheduleNormalPackage() { - dir(appPath, [ - libPubspec("test_pkg", "1.0.0"), - file("LICENSE", "Eh, do what you want.") - ]).scheduleCreate(); -} +Validator pubspecField(Entrypoint entrypoint) => + new PubspecFieldValidator(entrypoint); + +void scheduleNormalPackage() => normalPackage.scheduleCreate(); main() { group('should consider a package valid if it', () { @@ -93,6 +91,17 @@ main() { expectNoValidationError(name); run(); }); + + test('has a non-Dart file in lib', () { + dir(appPath, [ + libPubspec("test_pkg", "1.0.0"), + dir("lib", [ + file("thing.txt", "woo hoo") + ]) + ]).scheduleCreate(); + expectNoValidationError(lib); + run(); + }); }); group('should consider a package invalid if it', () { @@ -242,5 +251,28 @@ main() { expectValidationError(name); run(); }); + + test('has no lib directory', () { + dir(join(appPath, "lib")).scheduleDelete(); + expectValidationError(lib); + run(); + }); + + test('has an empty lib directory', () { + file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete(); + expectValidationError(lib); + run(); + }); + + test('has a lib directory containing only src', () { + file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete(); + dir(appPath, [ + dir("lib", [ + dir("src", [file("test_pkg.dart", "int i = 0;")]) + ]) + ]).scheduleCreate(); + expectValidationError(lib); + run(); + }); }); }