From 1a9fed77c0e29e98d8c30151bce9cb5680e8b55c Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 23 Jul 2014 23:32:06 +0000 Subject: [PATCH 001/281] Move pub/barback's Pool class into its own package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//399963004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/pool@38525 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/pool/LICENSE | 26 +++++++ pkgs/pool/README.md | 53 +++++++++++++ pkgs/pool/lib/pool.dart | 139 ++++++++++++++++++++++++++++++++++ pkgs/pool/pubspec.yaml | 7 ++ pkgs/pool/test/pool_test.dart | 137 +++++++++++++++++++++++++++++++++ 5 files changed, 362 insertions(+) create mode 100644 pkgs/pool/LICENSE create mode 100644 pkgs/pool/README.md create mode 100644 pkgs/pool/lib/pool.dart create mode 100644 pkgs/pool/pubspec.yaml create mode 100644 pkgs/pool/test/pool_test.dart diff --git a/pkgs/pool/LICENSE b/pkgs/pool/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/pool/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/pool/README.md b/pkgs/pool/README.md new file mode 100644 index 000000000..898728867 --- /dev/null +++ b/pkgs/pool/README.md @@ -0,0 +1,53 @@ +The pool package exposes a `Pool` class which makes it easy to manage a limited +pool of resources. + +The easiest way to use a pool is by calling `withResource`. This runs a callback +and returns its result, but only once there aren't too many other callbacks +currently running. + +```dart +// Create a Pool that will only allocate 10 resources at once. After 30 seconds +// of inactivity with all resources checked out, the pool will throw an error. +final pool = new Pool(10, timeout: new Duration(seconds: 30)); + +Future readFile(String path) { + // Since the call to [File.readAsString] is within [withResource], no more + // than ten files will be open at once. + return pool.withResource(() => return new File(path).readAsString()); +} +``` + +For more fine-grained control, the user can also explicitly request generic +`PoolResource` objects that can later be released back into the pool. This is +what `withResource` does under the covers: requests a resource, then releases it +once the callback completes. + +`Pool` ensures that only a limited number of resources are allocated at once. +It's the caller's responsibility to ensure that the corresponding physical +resource is only consumed when a `PoolResource` is allocated. + +```dart +class PooledFile implements RandomAccessFile { + final RandomAccessFile _file; + final PoolResource _resource; + + static Future open(String path) { + return pool.request().then((resource) { + return new File(path).open().then((file) { + return new PooledFile._(file, resource); + }); + }); + } + + PooledFile(this._file, this._resource); + + // ... + + Future close() { + return _file.close.then((_) { + _resource.release(); + return this; + }); + } +} +``` diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart new file mode 100644 index 000000000..36a29c86d --- /dev/null +++ b/pkgs/pool/lib/pool.dart @@ -0,0 +1,139 @@ +// Copyright (c) 2014, 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 pool; + +import 'dart:async'; +import 'dart:collection'; + +import 'package:stack_trace/stack_trace.dart'; + +/// Manages an abstract pool of resources with a limit on how many may be in use +/// at once. +/// +/// When a resource is needed, the user should call [request]. When the returned +/// future completes with a [PoolResource], the resource may be allocated. Once +/// the resource has been released, the user should call [PoolResource.release]. +/// The pool will ensure that only a certain number of [PoolResource]s may be +/// allocated at once. +class Pool { + /// Completers for requests beyond the first [_maxAllocatedResources]. + /// + /// When an item is released, the next element of [_requestedResources] will + /// be completed. + final _requestedResources = new Queue>(); + + /// The maximum number of resources that may be allocated at once. + final int _maxAllocatedResources; + + /// The number of resources that are currently allocated. + int _allocatedResources = 0; + + /// The timeout timer. + /// + /// If [_timeout] isn't null, this timer is set as soon as the resource limit + /// is reached and is reset every time an resource is released or a new + /// resource is requested. If it fires, that indicates that the caller became + /// deadlocked, likely due to files waiting for additional files to be read + /// before they could be closed. + Timer _timer; + + /// The amount of time to wait before timing out the pending resources. + Duration _timeout; + + /// Creates a new pool with the given limit on how many resources may be + /// allocated at once. + /// + /// If [timeout] is passed, then if that much time passes without any activity + /// all pending [request] futures will throw an exception. This is indented + /// to avoid deadlocks. + Pool(this._maxAllocatedResources, {Duration timeout}) + : _timeout = timeout; + + /// Request a [PoolResource]. + /// + /// If the maximum number of resources is already allocated, this will delay + /// until one of them is released. + Future request() { + if (_allocatedResources < _maxAllocatedResources) { + _allocatedResources++; + return new Future.value(new PoolResource._(this)); + } else { + var completer = new Completer(); + _requestedResources.add(completer); + _resetTimer(); + return completer.future; + } + } + + /// Requests a resource for the duration of [callback], which may return a + /// Future. + /// + /// The return value of [callback] is piped to the returned Future. + Future withResource(callback()) { + return request().then((resource) => + Chain.track(new Future.sync(callback)).whenComplete(resource.release)); + } + + /// If there are any pending requests, this will fire the oldest one. + void _onResourceReleased() { + if (_requestedResources.isEmpty) { + _allocatedResources--; + if (_timer != null) { + _timer.cancel(); + _timer = null; + } + return; + } + + _resetTimer(); + var pending = _requestedResources.removeFirst(); + pending.complete(new PoolResource._(this)); + } + + /// A resource has been requested, allocated, or released. + void _resetTimer() { + if (_timer != null) _timer.cancel(); + if (_timeout == null) { + _timer = null; + } else { + _timer = new Timer(_timeout, _onTimeout); + } + } + + /// Handles [_timer] timing out by causing all pending resource completers to + /// emit exceptions. + void _onTimeout() { + for (var completer in _requestedResources) { + completer.completeError("Pool deadlock: all resources have been " + "allocated for too long.", new Chain.current()); + } + _requestedResources.clear(); + _timer = null; + } +} + +/// A member of a [Pool]. +/// +/// A [PoolResource] is a token that indicates that a resource is allocated. +/// When the associated resource is released, the user should call [release]. +class PoolResource { + final Pool _pool; + + /// Whether [this] has been released yet. + bool _released = false; + + PoolResource._(this._pool); + + /// Tells the parent [Pool] that the resource associated with this resource is + /// no longer allocated, and that a new [PoolResource] may be allocated. + void release() { + if (_released) { + throw new StateError("A PoolResource may only be released once."); + } + _released = true; + _pool._onResourceReleased(); + } +} + diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml new file mode 100644 index 000000000..847a5471b --- /dev/null +++ b/pkgs/pool/pubspec.yaml @@ -0,0 +1,7 @@ +name: pool +version: 1.0.0 +description: A class for managing a finite pool of resources. +dependencies: + stack_trace: ">=0.9.2 <2.0.0" +dev_dependencies: + unittest: ">=0.11.0 <0.12.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart new file mode 100644 index 000000000..40bcf8a74 --- /dev/null +++ b/pkgs/pool/test/pool_test.dart @@ -0,0 +1,137 @@ +// Copyright (c) 2014, 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. + +import 'dart:async'; + +import 'package:pool/pool.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +void main() { + group("request()", () { + test("resources can be requested freely up to the limit", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + }); + + test("resources block past the limit", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); + }); + + test("a blocked resource is allocated when another is released", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + return pool.request().then((lastAllocatedResource) { + var blockedResource = pool.request(); + + return pumpEventQueue().then((_) { + lastAllocatedResource.release(); + return pumpEventQueue(); + }).then((_) { + expect(blockedResource, completes); + }); + }); + }); + }); + + group("withResource()", () { + test("can be called freely up to the limit", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + }); + + test("blocks the callback past the limit", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + pool.withResource(expectNoAsync()); + }); + + test("a blocked resource is allocated when another is released", () { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + + var completer = new Completer(); + var lastAllocatedResource = pool.withResource(() => completer.future); + var blockedResourceAllocated = false; + var blockedResource = pool.withResource(() { + blockedResourceAllocated = true; + }); + + return pumpEventQueue().then((_) { + expect(blockedResourceAllocated, isFalse); + completer.complete(); + return pumpEventQueue(); + }).then((_) { + expect(blockedResourceAllocated, isTrue); + }); + }); + }); + + // TODO(nweiz): test timeouts when seaneagan's fake_async package lands. +} + +/// Returns a [Future] that completes after pumping the event queue [times] +/// times. By default, this should pump the event queue enough times to allow +/// any code to run, as long as it's not waiting on some external event. +Future pumpEventQueue([int times = 20]) { + if (times == 0) return new Future.value(); + // We use a delayed future to allow microtask events to finish. The + // Future.value or Future() constructors use scheduleMicrotask themselves and + // would therefore not wait for microtask callbacks that are scheduled after + // invoking this method. + return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); +} + +/// Returns a function that will cause the test to fail if it's called. +/// +/// This won't let the test complete until it's confident that the function +/// won't be called. +Function expectNoAsync() { + // Make sure the test lasts long enough for the function to get called if it's + // going to get called. + expect(pumpEventQueue(), completes); + + var stack = new Trace.current(1); + return () => handleExternalError( + new TestFailure("Expected function not to be called."), "", + stack); +} + +/// A matcher for Futures that asserts that they don't complete. +/// +/// This won't let the test complete until it's confident that the function +/// won't be called. +Matcher get doesNotComplete => predicate((future) { + expect(future, new isInstanceOf('Future')); + // Make sure the test lasts long enough for the function to get called if it's + // going to get called. + expect(pumpEventQueue(), completes); + + var stack = new Trace.current(1); + future.then((_) => handleExternalError( + new TestFailure("Expected future not to complete."), "", + stack)); + return true; +}); From 1487d08098e5f456e3e323cd2bed418799d1a7bb Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 24 Jul 2014 00:26:30 +0000 Subject: [PATCH 002/281] Make the pubspec for the pool package releasable. R=alanknight@google.com Review URL: https://codereview.chromium.org//415883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/pool@38528 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/pool/pubspec.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 847a5471b..c1d543f93 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,6 +1,8 @@ name: pool version: 1.0.0 +author: Dart Team description: A class for managing a finite pool of resources. +homepage: http://www.dartlang.org dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: From 3adf36b500f299002404d9ff1b68cb0cf9ca0ec0 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 24 Jul 2014 20:29:33 +0000 Subject: [PATCH 003/281] Add timeout tests for the pool package. R=alanknight@google.com Review URL: https://codereview.chromium.org//411263006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/pool@38552 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/pool/CHANGELOG.md | 3 + pkgs/pool/lib/pool.dart | 13 ++- pkgs/pool/pubspec.yaml | 3 +- pkgs/pool/test/pool_test.dart | 186 ++++++++++++++++++++++------------ 4 files changed, 133 insertions(+), 72 deletions(-) create mode 100644 pkgs/pool/CHANGELOG.md diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md new file mode 100644 index 000000000..e8dee50c9 --- /dev/null +++ b/pkgs/pool/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.1 + +* A `TimeoutException` is now correctly thrown if the pool detects a deadlock. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 36a29c86d..61482e3f2 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -40,14 +40,14 @@ class Pool { Timer _timer; /// The amount of time to wait before timing out the pending resources. - Duration _timeout; + final Duration _timeout; /// Creates a new pool with the given limit on how many resources may be /// allocated at once. /// /// If [timeout] is passed, then if that much time passes without any activity - /// all pending [request] futures will throw an exception. This is indented - /// to avoid deadlocks. + /// all pending [request] futures will throw a [TimeoutException]. This is + /// intended to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout; @@ -106,8 +106,11 @@ class Pool { /// emit exceptions. void _onTimeout() { for (var completer in _requestedResources) { - completer.completeError("Pool deadlock: all resources have been " - "allocated for too long.", new Chain.current()); + completer.completeError( + new TimeoutException("Pool deadlock: all resources have been " + "allocated for too long.", + _timeout), + new Chain.current()); } _requestedResources.clear(); _timer = null; diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index c1d543f93..9972cbbb3 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,9 +1,10 @@ name: pool -version: 1.0.0 +version: 1.0.1 author: Dart Team description: A class for managing a finite pool of resources. homepage: http://www.dartlang.org dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: + fake_async: ">=0.1.0 <0.2.0" unittest: ">=0.11.0 <0.12.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 40bcf8a74..bb9e60768 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:fake_async/fake_async.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -19,30 +20,36 @@ void main() { }); test("resources block past the limit", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - expect(pool.request(), doesNotComplete); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); + + async.elapse(new Duration(seconds: 1)); + }); }); test("a blocked resource is allocated when another is released", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - expect(pool.request(), completes); - } - - return pool.request().then((lastAllocatedResource) { - var blockedResource = pool.request(); - - return pumpEventQueue().then((_) { - lastAllocatedResource.release(); - return pumpEventQueue(); - }).then((_) { - expect(blockedResource, completes); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + pool.request().then((lastAllocatedResource) { + // This will only complete once [lastAllocatedResource] is released. + expect(pool.request(), completes); + + new Future.delayed(new Duration(microseconds: 1)).then((_) { + lastAllocatedResource.release(); + }); }); + + async.elapse(new Duration(seconds: 1)); }); }); }); @@ -57,62 +64,113 @@ void main() { }); test("blocks the callback past the limit", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } - pool.withResource(expectNoAsync()); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + pool.withResource(expectNoAsync()); + + async.elapse(new Duration(seconds: 1)); + }); }); test("a blocked resource is allocated when another is released", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + + var completer = new Completer(); + var lastAllocatedResource = pool.withResource(() => completer.future); + var blockedResourceAllocated = false; + var blockedResource = pool.withResource(() { + blockedResourceAllocated = true; + }); - var completer = new Completer(); - var lastAllocatedResource = pool.withResource(() => completer.future); - var blockedResourceAllocated = false; - var blockedResource = pool.withResource(() { - blockedResourceAllocated = true; - }); + new Future.delayed(new Duration(microseconds: 1)).then((_) { + expect(blockedResourceAllocated, isFalse); + completer.complete(); + return new Future.delayed(new Duration(microseconds: 1)); + }).then((_) { + expect(blockedResourceAllocated, isTrue); + }); - return pumpEventQueue().then((_) { - expect(blockedResourceAllocated, isFalse); - completer.complete(); - return pumpEventQueue(); - }).then((_) { - expect(blockedResourceAllocated, isTrue); + async.elapse(new Duration(seconds: 1)); }); }); }); - // TODO(nweiz): test timeouts when seaneagan's fake_async package lands. -} + group("with a timeout", () { + test("doesn't time out if there are no pending requests", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } -/// Returns a [Future] that completes after pumping the event queue [times] -/// times. By default, this should pump the event queue enough times to allow -/// any code to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times = 20]) { - if (times == 0) return new Future.value(); - // We use a delayed future to allow microtask events to finish. The - // Future.value or Future() constructors use scheduleMicrotask themselves and - // would therefore not wait for microtask callbacks that are scheduled after - // invoking this method. - return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("resets the timer if a resource is returned", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + pool.request().then((lastAllocatedResource) { + // This will only complete once [lastAllocatedResource] is released. + expect(pool.request(), completes); + + new Future.delayed(new Duration(seconds: 3)).then((_) { + lastAllocatedResource.release(); + expect(pool.request(), doesNotComplete); + }); + }); + + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("resets the timer if a resource is requested", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); + + new Future.delayed(new Duration(seconds: 3)).then((_) { + expect(pool.request(), doesNotComplete); + }); + + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("times out if nothing happens", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), throwsA(new isInstanceOf())); + + async.elapse(new Duration(seconds: 6)); + }); + }); + }); } /// Returns a function that will cause the test to fail if it's called. /// -/// This won't let the test complete until it's confident that the function -/// won't be called. +/// This should only be called within a [FakeAsync.run] zone. Function expectNoAsync() { - // Make sure the test lasts long enough for the function to get called if it's - // going to get called. - expect(pumpEventQueue(), completes); - var stack = new Trace.current(1); return () => handleExternalError( new TestFailure("Expected function not to be called."), "", @@ -121,13 +179,9 @@ Function expectNoAsync() { /// A matcher for Futures that asserts that they don't complete. /// -/// This won't let the test complete until it's confident that the function -/// won't be called. +/// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { expect(future, new isInstanceOf('Future')); - // Make sure the test lasts long enough for the function to get called if it's - // going to get called. - expect(pumpEventQueue(), completes); var stack = new Trace.current(1); future.then((_) => handleExternalError( From 2686535940bdbe2664d4c1bd0012988038add009 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 25 Jul 2014 00:32:40 +0000 Subject: [PATCH 004/281] Revert r38549, r38552, and r38557. It's currently too difficult to include a third party package for it to be worthwhile for this use case. R=alanknight@google.com Review URL: https://codereview.chromium.org//419683002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/pool@38564 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/pool/CHANGELOG.md | 3 - pkgs/pool/lib/pool.dart | 13 +-- pkgs/pool/pubspec.yaml | 3 +- pkgs/pool/test/pool_test.dart | 187 ++++++++++++---------------------- 4 files changed, 73 insertions(+), 133 deletions(-) delete mode 100644 pkgs/pool/CHANGELOG.md diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md deleted file mode 100644 index e8dee50c9..000000000 --- a/pkgs/pool/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 1.0.1 - -* A `TimeoutException` is now correctly thrown if the pool detects a deadlock. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 61482e3f2..36a29c86d 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -40,14 +40,14 @@ class Pool { Timer _timer; /// The amount of time to wait before timing out the pending resources. - final Duration _timeout; + Duration _timeout; /// Creates a new pool with the given limit on how many resources may be /// allocated at once. /// /// If [timeout] is passed, then if that much time passes without any activity - /// all pending [request] futures will throw a [TimeoutException]. This is - /// intended to avoid deadlocks. + /// all pending [request] futures will throw an exception. This is indented + /// to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout; @@ -106,11 +106,8 @@ class Pool { /// emit exceptions. void _onTimeout() { for (var completer in _requestedResources) { - completer.completeError( - new TimeoutException("Pool deadlock: all resources have been " - "allocated for too long.", - _timeout), - new Chain.current()); + completer.completeError("Pool deadlock: all resources have been " + "allocated for too long.", new Chain.current()); } _requestedResources.clear(); _timer = null; diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 9972cbbb3..c1d543f93 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,9 @@ name: pool -version: 1.0.1 +version: 1.0.0 author: Dart Team description: A class for managing a finite pool of resources. homepage: http://www.dartlang.org dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: - fake_async: ">=0.1.0 <0.2.0" unittest: ">=0.11.0 <0.12.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index bb9e60768..bfeb876b1 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:fake_async/fake_async.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -20,36 +19,30 @@ void main() { }); test("resources block past the limit", () { - new FakeAsync().run((async) { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - expect(pool.request(), doesNotComplete); - - async.elapse(new Duration(seconds: 1)); - }); + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); }); test("a blocked resource is allocated when another is released", () { - new FakeAsync().run((async) { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - expect(pool.request(), completes); - } - - pool.request().then((lastAllocatedResource) { - // This will only complete once [lastAllocatedResource] is released. - expect(pool.request(), completes); - - new Future.delayed(new Duration(microseconds: 1)).then((_) { - lastAllocatedResource.release(); - }); - }); + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + return pool.request().then((lastAllocatedResource) { + var blockedResource = pool.request(); - async.elapse(new Duration(seconds: 1)); + return pumpEventQueue().then((_) { + lastAllocatedResource.release(); + return pumpEventQueue(); + }).then((_) { + expect(blockedResource, completes); + }); }); }); }); @@ -64,113 +57,63 @@ void main() { }); test("blocks the callback past the limit", () { - new FakeAsync().run((async) { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } - pool.withResource(expectNoAsync()); - - async.elapse(new Duration(seconds: 1)); - }); + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + pool.withResource(expectNoAsync()); }); test("a blocked resource is allocated when another is released", () { - new FakeAsync().run((async) { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } - - var completer = new Completer(); - var lastAllocatedResource = pool.withResource(() => completer.future); - var blockedResourceAllocated = false; - var blockedResource = pool.withResource(() { - blockedResourceAllocated = true; - }); - - new Future.delayed(new Duration(microseconds: 1)).then((_) { - expect(blockedResourceAllocated, isFalse); - completer.complete(); - return new Future.delayed(new Duration(microseconds: 1)); - }).then((_) { - expect(blockedResourceAllocated, isTrue); - }); + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } - async.elapse(new Duration(seconds: 1)); + var completer = new Completer(); + var lastAllocatedResource = pool.withResource(() => completer.future); + var blockedResourceAllocated = false; + var blockedResource = pool.withResource(() { + blockedResourceAllocated = true; }); - }); - }); - - group("with a timeout", () { - test("doesn't time out if there are no pending requests", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - async.elapse(new Duration(seconds: 6)); + return pumpEventQueue().then((_) { + expect(blockedResourceAllocated, isFalse); + completer.complete(); + return pumpEventQueue(); + }).then((_) { + expect(blockedResourceAllocated, isTrue); }); }); + }); - test("resets the timer if a resource is returned", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); - for (var i = 0; i < 49; i++) { - expect(pool.request(), completes); - } - - pool.request().then((lastAllocatedResource) { - // This will only complete once [lastAllocatedResource] is released. - expect(pool.request(), completes); - - new Future.delayed(new Duration(seconds: 3)).then((_) { - lastAllocatedResource.release(); - expect(pool.request(), doesNotComplete); - }); - }); - - async.elapse(new Duration(seconds: 6)); - }); - }); - - test("resets the timer if a resource is requested", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - expect(pool.request(), doesNotComplete); - - new Future.delayed(new Duration(seconds: 3)).then((_) { - expect(pool.request(), doesNotComplete); - }); - - async.elapse(new Duration(seconds: 6)); - }); - }); - - test("times out if nothing happens", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - expect(pool.request(), throwsA(new isInstanceOf())); + // TODO(nweiz): Test timeouts when it's easier to use third-party packages. + // See r38552. +} - async.elapse(new Duration(seconds: 6)); - }); - }); - }); +/// Returns a [Future] that completes after pumping the event queue [times] +/// times. By default, this should pump the event queue enough times to allow +/// any code to run, as long as it's not waiting on some external event. +Future pumpEventQueue([int times = 20]) { + if (times == 0) return new Future.value(); + // We use a delayed future to allow microtask events to finish. The + // Future.value or Future() constructors use scheduleMicrotask themselves and + // would therefore not wait for microtask callbacks that are scheduled after + // invoking this method. + return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); } /// Returns a function that will cause the test to fail if it's called. /// -/// This should only be called within a [FakeAsync.run] zone. +/// This won't let the test complete until it's confident that the function +/// won't be called. Function expectNoAsync() { + // Make sure the test lasts long enough for the function to get called if it's + // going to get called. + expect(pumpEventQueue(), completes); + var stack = new Trace.current(1); return () => handleExternalError( new TestFailure("Expected function not to be called."), "", @@ -179,9 +122,13 @@ Function expectNoAsync() { /// A matcher for Futures that asserts that they don't complete. /// -/// This should only be called within a [FakeAsync.run] zone. +/// This won't let the test complete until it's confident that the function +/// won't be called. Matcher get doesNotComplete => predicate((future) { expect(future, new isInstanceOf('Future')); + // Make sure the test lasts long enough for the function to get called if it's + // going to get called. + expect(pumpEventQueue(), completes); var stack = new Trace.current(1); future.then((_) => handleExternalError( From d2cce51db09b1d567dfd516706397ee891035ba9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:23:10 -0800 Subject: [PATCH 005/281] Add gitignore, status, and codereview files. --- pkgs/pool/.gitignore | 14 ++++++++++++++ pkgs/pool/.status | 3 +++ pkgs/pool/codereview.settings | 3 +++ 3 files changed, 20 insertions(+) create mode 100644 pkgs/pool/.gitignore create mode 100644 pkgs/pool/.status create mode 100644 pkgs/pool/codereview.settings diff --git a/pkgs/pool/.gitignore b/pkgs/pool/.gitignore new file mode 100644 index 000000000..388eff0ba --- /dev/null +++ b/pkgs/pool/.gitignore @@ -0,0 +1,14 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file diff --git a/pkgs/pool/.status b/pkgs/pool/.status new file mode 100644 index 000000000..e9f2b0049 --- /dev/null +++ b/pkgs/pool/.status @@ -0,0 +1,3 @@ +# Copyright (c) 2014, 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. diff --git a/pkgs/pool/codereview.settings b/pkgs/pool/codereview.settings new file mode 100644 index 000000000..b474c08cb --- /dev/null +++ b/pkgs/pool/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/pool/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From ab0b997d6298e65923c45838354a5c5b9ac81d08 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:23:25 -0800 Subject: [PATCH 006/281] Update the pubspec's homepage link. --- pkgs/pool/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index c1d543f93..b6a0ff299 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -2,7 +2,7 @@ name: pool version: 1.0.0 author: Dart Team description: A class for managing a finite pool of resources. -homepage: http://www.dartlang.org +homepage: http://github.com/dart-lang/pool dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: From fa368609ce721202319196d28e3b8c3d3b6daa3a Mon Sep 17 00:00:00 2001 From: pquitslund Date: Wed, 13 May 2015 13:38:29 -0700 Subject: [PATCH 007/281] Initial template commit. --- pkgs/package_config/.gitignore | 7 +++ pkgs/package_config/.travis.yml | 3 ++ pkgs/package_config/AUTHORS | 6 +++ pkgs/package_config/CHANGELOG.md | 5 ++ pkgs/package_config/CONTRIBUTING.md | 33 ++++++++++++ pkgs/package_config/LICENSE | 26 +++++++++ pkgs/package_config/README.md | 11 ++++ pkgs/package_config/pubspec.lock | 83 +++++++++++++++++++++++++++++ pkgs/package_config/pubspec.yaml | 11 ++++ pkgs/package_config/test/all.dart | 9 ++++ pkgs/package_config/tool/travis.sh | 16 ++++++ 11 files changed, 210 insertions(+) create mode 100644 pkgs/package_config/.gitignore create mode 100644 pkgs/package_config/.travis.yml create mode 100644 pkgs/package_config/AUTHORS create mode 100644 pkgs/package_config/CHANGELOG.md create mode 100644 pkgs/package_config/CONTRIBUTING.md create mode 100644 pkgs/package_config/LICENSE create mode 100644 pkgs/package_config/README.md create mode 100644 pkgs/package_config/pubspec.lock create mode 100644 pkgs/package_config/pubspec.yaml create mode 100644 pkgs/package_config/test/all.dart create mode 100755 pkgs/package_config/tool/travis.sh diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore new file mode 100644 index 000000000..f48e3c9a8 --- /dev/null +++ b/pkgs/package_config/.gitignore @@ -0,0 +1,7 @@ +.idea +.pub +packages +build +.project +.settings +pubspec.lock \ No newline at end of file diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml new file mode 100644 index 000000000..b1279b7e4 --- /dev/null +++ b/pkgs/package_config/.travis.yml @@ -0,0 +1,3 @@ +language: dart +script: ./tool/travis.sh +sudo: false diff --git a/pkgs/package_config/AUTHORS b/pkgs/package_config/AUTHORS new file mode 100644 index 000000000..e8063a8cd --- /dev/null +++ b/pkgs/package_config/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md new file mode 100644 index 000000000..2a2d63cf8 --- /dev/null +++ b/pkgs/package_config/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.0.1 + +- Initial version diff --git a/pkgs/package_config/CONTRIBUTING.md b/pkgs/package_config/CONTRIBUTING.md new file mode 100644 index 000000000..6f5e0ea67 --- /dev/null +++ b/pkgs/package_config/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/package_config/LICENSE b/pkgs/package_config/LICENSE new file mode 100644 index 000000000..de31e1a0a --- /dev/null +++ b/pkgs/package_config/LICENSE @@ -0,0 +1,26 @@ +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md new file mode 100644 index 000000000..17d199b4a --- /dev/null +++ b/pkgs/package_config/README.md @@ -0,0 +1,11 @@ +# package_config + +Support for working with **Package Resolution Configuration** files as described +in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), +under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: https://github.com/dart-lang/package_config/issues diff --git a/pkgs/package_config/pubspec.lock b/pkgs/package_config/pubspec.lock new file mode 100644 index 000000000..197d32ed6 --- /dev/null +++ b/pkgs/package_config/pubspec.lock @@ -0,0 +1,83 @@ +# Generated by pub +# See http://pub.dartlang.org/doc/glossary.html#lockfile +packages: + analyzer: + description: analyzer + source: hosted + version: "0.25.0+1" + args: + description: args + source: hosted + version: "0.13.0" + barback: + description: barback + source: hosted + version: "0.15.2+4" + collection: + description: collection + source: hosted + version: "1.1.1" + crypto: + description: crypto + source: hosted + version: "0.9.0" + http_parser: + description: http_parser + source: hosted + version: "0.0.2+6" + matcher: + description: matcher + source: hosted + version: "0.12.0" + mime: + description: mime + source: hosted + version: "0.9.3" + path: + description: path + source: hosted + version: "1.3.5" + pool: + description: pool + source: hosted + version: "1.0.1" + pub_semver: + description: pub_semver + source: hosted + version: "1.2.0" + shelf: + description: shelf + source: hosted + version: "0.6.1+2" + shelf_static: + description: shelf_static + source: hosted + version: "0.2.2" + shelf_web_socket: + description: shelf_web_socket + source: hosted + version: "0.0.1+2" + source_span: + description: source_span + source: hosted + version: "1.1.2" + stack_trace: + description: stack_trace + source: hosted + version: "1.3.2" + string_scanner: + description: string_scanner + source: hosted + version: "0.1.3+1" + test: + description: test + source: hosted + version: "0.12.1" + watcher: + description: watcher + source: hosted + version: "0.9.5" + yaml: + description: yaml + source: hosted + version: "2.1.2" diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml new file mode 100644 index 000000000..b0f2d8fec --- /dev/null +++ b/pkgs/package_config/pubspec.yaml @@ -0,0 +1,11 @@ +name: package_config +version: 0.0.1 +description: Support for working with Package Resolution config files. +author: Dart Team +homepage: https://github.com/dart-lang/package_config + +environment: + sdk: '>=1.0.0 <2.0.0' + +dev_dependencies: + test: '>=0.12.0 <0.13.0' diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart new file mode 100644 index 000000000..76284af2b --- /dev/null +++ b/pkgs/package_config/test/all.dart @@ -0,0 +1,9 @@ +// Copyright (c) 2015, 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. + +import 'package:test/test.dart'; + +main() { + // TODO: add tests! +} diff --git a/pkgs/package_config/tool/travis.sh b/pkgs/package_config/tool/travis.sh new file mode 100755 index 000000000..8fdabfdf6 --- /dev/null +++ b/pkgs/package_config/tool/travis.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright (c) 2015, 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. + +# Fast fail the script on failures. +set -e + +# Verify that the libraries are error free. +dartanalyzer --fatal-warnings \ + test/all.dart + +# Run the tests. +dart test/all.dart + From 0ede819f2cd3d377b77cb6c0671398a474cc4a9e Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 13 May 2015 14:05:08 -0700 Subject: [PATCH 008/281] Update README.md Added build badge. --- pkgs/package_config/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 17d199b4a..140c3c4f9 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,6 +4,9 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg)](https://travis-ci.org/dart-lang/linter) + + ## Features and bugs Please file feature requests and bugs at the [issue tracker][tracker]. From 8aac6f18fd215ae16a164536bf74c50fecf63f81 Mon Sep 17 00:00:00 2001 From: pquitslund Date: Wed, 13 May 2015 14:25:23 -0700 Subject: [PATCH 009/281] Initial parser port. --- pkgs/package_config/lib/packagemap.dart | 227 ++++++++++++++++++ pkgs/package_config/test/all.dart | 4 +- pkgs/package_config/test/test_packagemap.dart | 149 ++++++++++++ pkgs/package_config/tool/travis.sh | 1 + 4 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 pkgs/package_config/lib/packagemap.dart create mode 100644 pkgs/package_config/test/test_packagemap.dart diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart new file mode 100644 index 000000000..046aa5221 --- /dev/null +++ b/pkgs/package_config/lib/packagemap.dart @@ -0,0 +1,227 @@ +// Copyright (c) 2015, 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 package_config.packagemap; + +class Packages { + static const int _EQUALS = 0x3d; + static const int _CR = 0x0d; + static const int _NL = 0x0a; + static const int _NUMBER_SIGN = 0x23; + + final Map packageMapping; + + Packages(this.packageMapping); + + /// Resolves a URI to a non-package URI. + /// + /// If [uri] is a `package:` URI, the location is resolved wrt. the + /// [packageMapping]. + /// Otherwise the original URI is returned. + Uri resolve(Uri uri) { + if (uri.scheme.toLowerCase() != "package") { + return uri; + } + if (uri.hasAuthority) { + throw new ArgumentError.value(uri, "uri", "Must not have authority"); + } + if (uri.path.startsWith("/")) { + throw new ArgumentError.value(uri, "uri", + "Path must not start with '/'."); + } + // Normalizes the path by removing '.' and '..' segments. + uri = uri.normalizePath(); + String path = uri.path; + var slashIndex = path.indexOf('/'); + String packageName; + String rest; + if (slashIndex < 0) { + packageName = path; + rest = ""; + } else { + packageName = path.substring(0, slashIndex); + rest = path.substring(slashIndex + 1); + } + Uri packageLocation = packageMapping[packageName]; + if (packageLocation == null) { + throw new ArgumentError.value(uri, "uri", + "Unknown package name: $packageName"); + } + return packageLocation.resolveUri(new Uri(path: rest)); + } + + /// Parses a `packages.cfg` file into a `Packages` object. + /// + /// The [baseLocation] is used as a base URI to resolve all relative + /// URI references against. + /// + /// The `Packages` object allows resolving package: URIs and writing + /// the mapping back to a file or string. + /// The [packageMapping] will contain a simple mapping from package name + /// to package location. + static Packages parse(String source, Uri baseLocation) { + int index = 0; + Map result = {}; + while (index < source.length) { + bool isComment = false; + int start = index; + int eqIndex = -1; + int end = source.length; + int char = source.codeUnitAt(index++); + if (char == _CR || char == _NL) { + continue; + } + if (char == _EQUALS) { + throw new FormatException("Missing package name", source, index - 1); + } + isComment = char == _NUMBER_SIGN; + while (index < source.length) { + char = source.codeUnitAt(index++); + if (char == _EQUALS && eqIndex < 0) { + eqIndex = index - 1; + } else if (char == _NL || char == _CR) { + end = index - 1; + break; + } + } + if (isComment) continue; + if (eqIndex < 0) { + throw new FormatException("No '=' on line", source, index - 1); + } + _checkIdentifier(source, start, eqIndex); + var packageName = source.substring(start, eqIndex); + + var packageLocation = Uri.parse(source, eqIndex + 1, end); + if (!packageLocation.path.endsWith('/')) { + packageLocation = packageLocation.replace( + path: packageLocation.path + "/"); + } + packageLocation = baseLocation.resolveUri(packageLocation); + if (result.containsKey(packageName)) { + throw new FormatException("Same package name occured twice.", + source, start); + } + result[packageName] = packageLocation; + } + return new Packages(result); + } + + /** + * Writes the mapping to a [StringSink]. + * + * If [comment] is provided, the output will contain this comment + * with `#` in front of each line. + * + * If [baseUri] is provided, package locations will be made relative + * to the base URI, if possible, before writing. + */ + void write(StringSink output, {Uri baseUri, String comment}) { + if (baseUri != null && !baseUri.isAbsolute) { + throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); + } + + if (comment != null) { + for (var commentLine in comment.split('\n')) { + output.write('#'); + output.writeln(commentLine); + } + } else { + output.write("# generated by package:packagecfg at "); + output.write(new DateTime.now()); + output.writeln(); + } + + packageMapping.forEach((String packageName, Uri uri) { + // Validate packageName. + _checkIdentifier(packageName, 0, packageName.length); + output.write(packageName); + + output.write('='); + + // If baseUri provided, make uri relative. + if (baseUri != null) { + uri = _relativizeUri(uri, baseUri); + } + output.write(uri); + if (!uri.path.endsWith('/')) { + output.write('/'); + } + output.writeln(); + }); + } + + String toString() { + StringBuffer buffer = new StringBuffer(); + write(buffer); + return buffer.toString(); + } + + static Uri relativize(Uri uri, + Uri baseUri) { + if (uri.hasQuery || uri.hasFragment) { + uri = new Uri(scheme: uri.scheme, + userInfo: uri.hasAuthority ? uri.userInfo : null, + host: uri.hasAuthority ? uri.host : null, + port: uri.hasAuthority ? uri.port : null, + path: uri.path); + } + if (!baseUri.isAbsolute) { + throw new ArgumentError("Base uri '$baseUri' must be absolute."); + } + // Already relative. + if (!uri.isAbsolute) return uri; + + if (baseUri.scheme.toLowerCase() != uri.scheme.toLowerCase()) { + return uri; + } + // If authority differs, we could remove the scheme, but it's not worth it. + if (uri.hasAuthority != baseUri.hasAuthority) return uri; + if (uri.hasAuthority) { + if (uri.userInfo != baseUri.userInfo || + uri.host.toLowerCase() != baseUri.host.toLowerCase() || + uri.port != baseUri.port) { + return uri; + } + } + + List base = baseUri.pathSegments.toList(); + base = base.normalizePath(); + if (base.isNotEmpty) { + base = new List.from(base)..removeLast(); + } + List target = uri.pathSegments.toList(); + target = target.normalizePath(); + int index = 0; + while (index < base.length && index < target.length) { + if (base[index] != target[index]) { + break; + } + index++; + } + if (index == base.length) { + return new Uri(path: target.skip(index).join('/')); + } else if (index > 0) { + return new Uri( + path: '../' * (base.length - index) + target.skip(index).join('/')); + } else { + return uri; + } + } + + static void _checkIdentifier(String string, int start, int end) { + const int a = 0x61; + const int z = 0x7a; + const int _ = 0x5f; + const int $ = 0x24; + if (start == end) return false; + for (int i = start; i < end; i++) { + var char = string.codeUnitAt(i); + if (char == _ || char == $) continue; + if ((char ^ 0x30) <= 9 && i > 0) continue; + char |= 0x20; // Lower-case letters. + if (char >= a && char <= z) continue; + throw new FormatException("Not an identifier", string, i); + } + } +} \ No newline at end of file diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart index 76284af2b..795289cdf 100644 --- a/pkgs/package_config/test/all.dart +++ b/pkgs/package_config/test/all.dart @@ -2,8 +2,8 @@ // 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. -import 'package:test/test.dart'; +import 'test_packagemap.dart' as packagemap; main() { - // TODO: add tests! + packagemap.main(); } diff --git a/pkgs/package_config/test/test_packagemap.dart b/pkgs/package_config/test/test_packagemap.dart new file mode 100644 index 000000000..bce20d4b8 --- /dev/null +++ b/pkgs/package_config/test/test_packagemap.dart @@ -0,0 +1,149 @@ +// Copyright (c) 2015, 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 test_all; + +import "package:package_config/packagemap.dart"; +import "package:test/test.dart"; + +main() { + var base = Uri.parse("file:///one/two/three/packages.map"); + test("empty", () { + var packages = Packages.parse(emptySample, base); + expect(packages.packageMapping, isEmpty); + }); + test("comment only", () { + var packages = Packages.parse(commentOnlySample, base); + expect(packages.packageMapping, isEmpty); + }); + test("empty lines only", () { + var packages = Packages.parse(emptyLinesSample, base); + expect(packages.packageMapping, isEmpty); + }); + + test("empty lines only", () { + var packages = Packages.parse(emptyLinesSample, base); + expect(packages.packageMapping, isEmpty); + }); + + test("single", () { + var packages = Packages.parse(singleRelativeSample, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single no slash", () { + var packages = Packages.parse(singleRelativeSampleNoSlash, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single no newline", () { + var packages = Packages.parse(singleRelativeSampleNoNewline, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single absolute", () { + var packages = Packages.parse(singleAbsoluteSample, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); + }); + + test("multiple", () { + var packages = Packages.parse(multiRelativeSample, base); + expect( + packages.packageMapping.keys.toList()..sort(), equals(["bar", "foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), + equals(base.resolve("../test2/").resolve("foo/baz.dart"))); + }); + + test("dot-dot 1", () { + var packages = Packages.parse(singleRelativeSample, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("dot-dot 2", () { + var packages = Packages.parse(singleRelativeSample, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("all valid chars", () { + var packages = Packages.parse(allValidCharsSample, base); + expect(packages.packageMapping.keys.toList(), equals([allValidChars])); + expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("no escapes", () { + expect(() => Packages.parse("x%41x=x", base), throws); + }); + + test("not identifiers", () { + expect(() => Packages.parse("1x=x", base), throws); + expect(() => Packages.parse(" x=x", base), throws); + expect(() => Packages.parse("\\x41x=x", base), throws); + expect(() => Packages.parse("x@x=x", base), throws); + expect(() => Packages.parse("x[x=x", base), throws); + expect(() => Packages.parse("x`x=x", base), throws); + expect(() => Packages.parse("x{x=x", base), throws); + expect(() => Packages.parse("x/x=x", base), throws); + expect(() => Packages.parse("x:x=x", base), throws); + }); + + test("same name twice", () { + expect(() => Packages.parse(singleRelativeSample * 2, base), throws); + }); + + for (String invalidSample in invalid) { + test("invalid '$invalidSample'", () { + var result; + try { + result = Packages.parse(invalidSample, base); + } on FormatException { + // expected + return; + } + fail("Resolved to $result"); + }); + } +} + +// Valid samples. +var emptySample = ""; +var commentOnlySample = "# comment only\n"; +var emptyLinesSample = "\n\n\r\n"; +var singleRelativeSample = "foo=../test/\n"; +var singleRelativeSampleNoSlash = "foo=../test\n"; +var singleRelativeSampleNoNewline = "foo=../test/"; +var singleAbsoluteSample = "foo=http://example.com/some/where/\n"; +var multiRelativeSample = "foo=../test/\nbar=../test2/\n"; +// All valid path segment characters in an URI. +var allValidChars = + r"$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; +var allValidCharsSample = "${allValidChars.replaceAll('=', '%3D')}=../test/\n"; +var allUnreservedChars = + "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; + +// Invalid samples. +var invalid = [ + "foobar:baz.dart", // no equals + ".=../test/", // dot segment + "..=../test/", // dot-dot segment + "foo/bar=../test/", // + "/foo=../test/", // var multiSegmentSample + "?=../test/", // invalid characters in path segment. + "[=../test/", // invalid characters in path segment. + "x#=../test/", // invalid characters in path segment. +]; diff --git a/pkgs/package_config/tool/travis.sh b/pkgs/package_config/tool/travis.sh index 8fdabfdf6..82423816b 100755 --- a/pkgs/package_config/tool/travis.sh +++ b/pkgs/package_config/tool/travis.sh @@ -9,6 +9,7 @@ set -e # Verify that the libraries are error free. dartanalyzer --fatal-warnings \ + lib/packagemap.dart \ test/all.dart # Run the tests. From a1a4f439bd93755fa76df9eb558ba3a37099b3d8 Mon Sep 17 00:00:00 2001 From: pquitslund Date: Wed, 13 May 2015 14:44:16 -0700 Subject: [PATCH 010/281] Parser fixes. --- pkgs/package_config/lib/packagemap.dart | 47 +++++++++++++------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart index 046aa5221..25f27b9a2 100644 --- a/pkgs/package_config/lib/packagemap.dart +++ b/pkgs/package_config/lib/packagemap.dart @@ -27,8 +27,8 @@ class Packages { throw new ArgumentError.value(uri, "uri", "Must not have authority"); } if (uri.path.startsWith("/")) { - throw new ArgumentError.value(uri, "uri", - "Path must not start with '/'."); + throw new ArgumentError.value( + uri, "uri", "Path must not start with '/'."); } // Normalizes the path by removing '.' and '..' segments. uri = uri.normalizePath(); @@ -45,8 +45,8 @@ class Packages { } Uri packageLocation = packageMapping[packageName]; if (packageLocation == null) { - throw new ArgumentError.value(uri, "uri", - "Unknown package name: $packageName"); + throw new ArgumentError.value( + uri, "uri", "Unknown package name: $packageName"); } return packageLocation.resolveUri(new Uri(path: rest)); } @@ -94,13 +94,13 @@ class Packages { var packageLocation = Uri.parse(source, eqIndex + 1, end); if (!packageLocation.path.endsWith('/')) { - packageLocation = packageLocation.replace( - path: packageLocation.path + "/"); + packageLocation = + packageLocation.replace(path: packageLocation.path + "/"); } packageLocation = baseLocation.resolveUri(packageLocation); if (result.containsKey(packageName)) { - throw new FormatException("Same package name occured twice.", - source, start); + throw new FormatException( + "Same package name occured twice.", source, start); } result[packageName] = packageLocation; } @@ -141,7 +141,7 @@ class Packages { // If baseUri provided, make uri relative. if (baseUri != null) { - uri = _relativizeUri(uri, baseUri); + uri = relativize(uri, baseUri); } output.write(uri); if (!uri.path.endsWith('/')) { @@ -157,14 +157,14 @@ class Packages { return buffer.toString(); } - static Uri relativize(Uri uri, - Uri baseUri) { + static Uri relativize(Uri uri, Uri baseUri) { if (uri.hasQuery || uri.hasFragment) { - uri = new Uri(scheme: uri.scheme, - userInfo: uri.hasAuthority ? uri.userInfo : null, - host: uri.hasAuthority ? uri.host : null, - port: uri.hasAuthority ? uri.port : null, - path: uri.path); + uri = new Uri( + scheme: uri.scheme, + userInfo: uri.hasAuthority ? uri.userInfo : null, + host: uri.hasAuthority ? uri.host : null, + port: uri.hasAuthority ? uri.port : null, + path: uri.path); } if (!baseUri.isAbsolute) { throw new ArgumentError("Base uri '$baseUri' must be absolute."); @@ -179,19 +179,19 @@ class Packages { if (uri.hasAuthority != baseUri.hasAuthority) return uri; if (uri.hasAuthority) { if (uri.userInfo != baseUri.userInfo || - uri.host.toLowerCase() != baseUri.host.toLowerCase() || - uri.port != baseUri.port) { + uri.host.toLowerCase() != baseUri.host.toLowerCase() || + uri.port != baseUri.port) { return uri; } } + baseUri = baseUri.normalizePath(); List base = baseUri.pathSegments.toList(); - base = base.normalizePath(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } + uri = uri.normalizePath(); List target = uri.pathSegments.toList(); - target = target.normalizePath(); int index = 0; while (index < base.length && index < target.length) { if (base[index] != target[index]) { @@ -209,7 +209,7 @@ class Packages { } } - static void _checkIdentifier(String string, int start, int end) { + static bool _checkIdentifier(String string, int start, int end) { const int a = 0x61; const int z = 0x7a; const int _ = 0x5f; @@ -219,9 +219,10 @@ class Packages { var char = string.codeUnitAt(i); if (char == _ || char == $) continue; if ((char ^ 0x30) <= 9 && i > 0) continue; - char |= 0x20; // Lower-case letters. + char |= 0x20; // Lower-case letters. if (char >= a && char <= z) continue; throw new FormatException("Not an identifier", string, i); } + return true; } -} \ No newline at end of file +} From 8dc4c7c292f4a81a312427700b0f429ae5f82ed8 Mon Sep 17 00:00:00 2001 From: pquitslund Date: Wed, 13 May 2015 14:57:34 -0700 Subject: [PATCH 011/281] Backed out path normalization. --- pkgs/package_config/lib/packagemap.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart index 25f27b9a2..e05c14d15 100644 --- a/pkgs/package_config/lib/packagemap.dart +++ b/pkgs/package_config/lib/packagemap.dart @@ -30,8 +30,9 @@ class Packages { throw new ArgumentError.value( uri, "uri", "Path must not start with '/'."); } + //TODO: re-enable // Normalizes the path by removing '.' and '..' segments. - uri = uri.normalizePath(); + // uri = uri.normalizePath(); String path = uri.path; var slashIndex = path.indexOf('/'); String packageName; @@ -185,12 +186,14 @@ class Packages { } } - baseUri = baseUri.normalizePath(); + //TODO: normalize path + // baseUri = baseUri.normalizePath(); List base = baseUri.pathSegments.toList(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } - uri = uri.normalizePath(); + //TODO: normalize path + //uri = uri.normalizePath(); List target = uri.pathSegments.toList(); int index = 0; while (index < base.length && index < target.length) { From 4223760f55245869171c4b469ed1f1ce147b8c9f Mon Sep 17 00:00:00 2001 From: pquitslund Date: Wed, 13 May 2015 14:59:02 -0700 Subject: [PATCH 012/281] Backed out path normalization. --- pkgs/package_config/test/test_packagemap.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/package_config/test/test_packagemap.dart b/pkgs/package_config/test/test_packagemap.dart index bce20d4b8..2c03dba8b 100644 --- a/pkgs/package_config/test/test_packagemap.dart +++ b/pkgs/package_config/test/test_packagemap.dart @@ -72,12 +72,14 @@ main() { equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - test("dot-dot 2", () { - var packages = Packages.parse(singleRelativeSample, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); + +// TODO: re-enable when path normalization is in +// test("dot-dot 2", () { +// var packages = Packages.parse(singleRelativeSample, base); +// expect(packages.packageMapping.keys.toList(), equals(["foo"])); +// expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), +// equals(base.resolve("../test/").resolve("bar/baz.dart"))); +// }); test("all valid chars", () { var packages = Packages.parse(allValidCharsSample, base); From 9abb76046d9e8143e2268ea0b82764c82fb743ba Mon Sep 17 00:00:00 2001 From: pquitslund Date: Thu, 14 May 2015 10:26:42 -0700 Subject: [PATCH 013/281] Fixed path normalization. --- pkgs/package_config/lib/packagemap.dart | 13 +++++++------ pkgs/package_config/test/test_packagemap.dart | 14 ++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart index e05c14d15..46a17970f 100644 --- a/pkgs/package_config/lib/packagemap.dart +++ b/pkgs/package_config/lib/packagemap.dart @@ -30,9 +30,8 @@ class Packages { throw new ArgumentError.value( uri, "uri", "Path must not start with '/'."); } - //TODO: re-enable // Normalizes the path by removing '.' and '..' segments. - // uri = uri.normalizePath(); + uri = _normalizePath(uri); String path = uri.path; var slashIndex = path.indexOf('/'); String packageName; @@ -52,6 +51,10 @@ class Packages { return packageLocation.resolveUri(new Uri(path: rest)); } + /// A stand in for uri.normalizePath(), coming in 1.11 + static Uri _normalizePath(Uri existingUri) => + new Uri().resolveUri(existingUri); + /// Parses a `packages.cfg` file into a `Packages` object. /// /// The [baseLocation] is used as a base URI to resolve all relative @@ -186,14 +189,12 @@ class Packages { } } - //TODO: normalize path - // baseUri = baseUri.normalizePath(); + baseUri = _normalizePath(baseUri); List base = baseUri.pathSegments.toList(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } - //TODO: normalize path - //uri = uri.normalizePath(); + uri = _normalizePath(uri); List target = uri.pathSegments.toList(); int index = 0; while (index < base.length && index < target.length) { diff --git a/pkgs/package_config/test/test_packagemap.dart b/pkgs/package_config/test/test_packagemap.dart index 2c03dba8b..bce20d4b8 100644 --- a/pkgs/package_config/test/test_packagemap.dart +++ b/pkgs/package_config/test/test_packagemap.dart @@ -72,14 +72,12 @@ main() { equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - -// TODO: re-enable when path normalization is in -// test("dot-dot 2", () { -// var packages = Packages.parse(singleRelativeSample, base); -// expect(packages.packageMapping.keys.toList(), equals(["foo"])); -// expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), -// equals(base.resolve("../test/").resolve("bar/baz.dart"))); -// }); + test("dot-dot 2", () { + var packages = Packages.parse(singleRelativeSample, base); + expect(packages.packageMapping.keys.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); test("all valid chars", () { var packages = Packages.parse(allValidCharsSample, base); From fd35e58cd6133de83a64803a1300e1d4d20431a1 Mon Sep 17 00:00:00 2001 From: pquitslund Date: Thu, 14 May 2015 11:06:35 -0700 Subject: [PATCH 014/281] Fixed path normalization. --- pkgs/package_config/.travis.yml | 1 + pkgs/package_config/lib/packagemap.dart | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index b1279b7e4..7a20d25b2 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -1,3 +1,4 @@ language: dart +dart: dev script: ./tool/travis.sh sudo: false diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart index 46a17970f..25f27b9a2 100644 --- a/pkgs/package_config/lib/packagemap.dart +++ b/pkgs/package_config/lib/packagemap.dart @@ -31,7 +31,7 @@ class Packages { uri, "uri", "Path must not start with '/'."); } // Normalizes the path by removing '.' and '..' segments. - uri = _normalizePath(uri); + uri = uri.normalizePath(); String path = uri.path; var slashIndex = path.indexOf('/'); String packageName; @@ -51,10 +51,6 @@ class Packages { return packageLocation.resolveUri(new Uri(path: rest)); } - /// A stand in for uri.normalizePath(), coming in 1.11 - static Uri _normalizePath(Uri existingUri) => - new Uri().resolveUri(existingUri); - /// Parses a `packages.cfg` file into a `Packages` object. /// /// The [baseLocation] is used as a base URI to resolve all relative @@ -189,12 +185,12 @@ class Packages { } } - baseUri = _normalizePath(baseUri); + baseUri = baseUri.normalizePath(); List base = baseUri.pathSegments.toList(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } - uri = _normalizePath(uri); + uri = uri.normalizePath(); List target = uri.pathSegments.toList(); int index = 0; while (index < base.length && index < target.length) { From a13bf81ef7eff8a3ad9c754e3592a09a856485fc Mon Sep 17 00:00:00 2001 From: pquitslund Date: Thu, 14 May 2015 15:26:07 -0700 Subject: [PATCH 015/281] SDK constraint bump to pickup Uri.normalizePath(). --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index b0f2d8fec..7494fddb9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.11.0-dev.0.0 <2.0.0' dev_dependencies: test: '>=0.12.0 <0.13.0' From 1f27fad214f9e664b1438b3b1f555667a02edb8e Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 22 May 2015 12:43:32 +0200 Subject: [PATCH 016/281] Added .packages, packages/ discovery. Complete restructure of repository, splitting into several files. R=pquitslund@google.com Review URL: https://codereview.chromium.org//1142363005 --- pkgs/package_config/lib/discovery.dart | 160 ++++++++++++ pkgs/package_config/lib/packagemap.dart | 228 ------------------ pkgs/package_config/lib/packages.dart | 97 ++++++++ pkgs/package_config/lib/packages_file.dart | 172 +++++++++++++ .../package_config/lib/src/packages_impl.dart | 118 +++++++++ pkgs/package_config/lib/src/util.dart | 69 ++++++ pkgs/package_config/pubspec.lock | 8 + pkgs/package_config/pubspec.yaml | 5 + pkgs/package_config/test/all.dart | 4 +- .../{test_packagemap.dart => parse_test.dart} | 80 +++--- 10 files changed, 674 insertions(+), 267 deletions(-) create mode 100644 pkgs/package_config/lib/discovery.dart delete mode 100644 pkgs/package_config/lib/packagemap.dart create mode 100644 pkgs/package_config/lib/packages.dart create mode 100644 pkgs/package_config/lib/packages_file.dart create mode 100644 pkgs/package_config/lib/src/packages_impl.dart create mode 100644 pkgs/package_config/lib/src/util.dart rename pkgs/package_config/test/{test_packagemap.dart => parse_test.dart} (60%) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart new file mode 100644 index 000000000..78254eeba --- /dev/null +++ b/pkgs/package_config/lib/discovery.dart @@ -0,0 +1,160 @@ +// Copyright (c) 2015, 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 package_config.discovery; + +import "dart:async"; +import "dart:io" show Directory, File, FileSystemEntity; +import "package:path/path.dart" as path; +import "package:http/http.dart" as http; +import "packages.dart"; +import "packages_file.dart" as pkgfile show parse; +import "src/packages_impl.dart"; + +/// Discover the package configuration for a Dart script. +/// +/// The [baseUri] points to either the Dart script or its directory. +/// A package resolution strategy is found by going through the following steps, +/// and stopping when something is found. +/// +/// * Check if a `.packages` file exists in the same directory. +/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory +/// in the same directory, and resolve packages relative to that. +/// * If `baseUri`'s scheme *is* `file`: +/// * Check if a `packages` directory exists. +/// * Otherwise check each successive parent directory of `baseUri` for a +/// `.packages` file. +/// +/// If any of these tests succeed, a `Packages` class is returned. +/// Returns the constant [noPackages] if no resolution strategy is found. +/// +/// This function currently only supports `file`, `http` and `https` URIs. +/// It needs to be able to load a `.packages` file from the URI, so only +/// recognized schemes are accepted. +/// +/// To support other schemes, an optional [loader] function can be supplied. +/// It's called to load the `.packages` file for any unsupported scheme. +/// It must return the *contents* of the file identified by the URI it's given, +/// which should be a UTF-8 encoded `.packages` file, and must return an +/// error future if loading fails for any reason. +Future findPackages( + Uri baseUri, + {Future> loader(Uri unsupportedUri)}) { + if (baseUri.scheme == "file") { + return new Future.sync(() => findPackagesFromFile(baseUri)); + } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { + return findPackagesFromNonFile(baseUri, _httpGet); + } else if (loader != null) { + return findPackagesFromNonFile(baseUri, loader); + } else { + return new Future.value(Packages.noPackages); + } +} + +/// Find the location of the package resolution file/directory for a Dart file. +/// +/// Checks for a `.packages` file in the [workingDirectory]. +/// If not found, checks for a `packages` directory in the same directory. +/// If still not found, starts checking parent directories for +/// `.packages` until reaching the root directory. +/// +/// Returns a [File] object of a `.packages` file if one is found, or a +/// [Directory] object for the `packages/` directory if that is found. +FileSystemEntity _findPackagesFile(String workingDirectory) { + var dir = new Directory(workingDirectory); + if (!dir.isAbsolute) dir = dir.absolute; + if (!dir.existsSync()) { + throw new ArgumentError.value( + workingDirectory, "workingDirectory", "Directory does not exist."); + } + File checkForConfigFile(Directory directory) { + assert(directory.isAbsolute); + var file = new File(path.join(directory.path, ".packages")); + if (file.existsSync()) return file; + return null; + } + // Check for $cwd/.packages + var packagesCfgFile = checkForConfigFile(dir); + if (packagesCfgFile != null) return packagesCfgFile; + // Check for $cwd/packages/ + var packagesDir = new Directory(path.join(dir.path, "packages")); + if (packagesDir.existsSync()) return packagesDir; + // Check for cwd(/..)+/.packages + var parentDir = dir.parent; + while (parentDir.path != dir.path) { + packagesCfgFile = checkForConfigFile(parentDir); + if (packagesCfgFile != null) break; + dir = parentDir; + parentDir = dir.parent; + } + return packagesCfgFile; +} + +/// Finds a package resolution strategy for a local Dart script. +/// +/// The [fileBaseUri] points to either a Dart script or the directory of the +/// script. The `fileBaseUri` must be a `file:` URI. +/// +/// This function first tries to locate a `.packages` file in the `fileBaseUri` +/// directory. If that is not found, it instead checks for the presence of +/// a `packages/` directory in the same place. +/// If that also fails, it starts checking parent directories for a `.packages` +/// file, and stops if it finds it. +/// Otherwise it gives up and returns [Pacakges.noPackages]. +Packages findPackagesFromFile(Uri fileBaseUri) { + Uri baseDirectoryUri = fileBaseUri; + if (!fileBaseUri.path.endsWith('/')) { + baseDirectoryUri = baseDirectoryUri.resolve("."); + } + String baseDirectoryPath = baseDirectoryUri.toFilePath(); + FileSystemEntity location = _findPackagesFile(baseDirectoryPath); + if (location == null) return Packages.noPackages; + if (location is File) { + List fileBytes = location.readAsBytesSync(); + Map map = pkgfile.parse(fileBytes, + new Uri.file(location.path)); + return new MapPackages(map); + } + assert(location is Directory); + return new FilePackagesDirectoryPackages(location); +} + +/// Finds a package resolution strategy for a Dart script. +/// +/// The [nonFileUri] points to either a Dart script or the directory of the +/// script. +/// The [nonFileUri] should not be a `file:` URI since the algorithm for +/// finding a package resolution strategy is more elaborate for `file:` URIs. +/// In that case, use [findPackagesFile]. +/// +/// This function first tries to locate a `.packages` file in the [nonFileUri] +/// directory. If that is not found, it instead assumes a `packages/` directory +/// in the same place. +/// +/// By default, this function only works for `http:` and `https:` URIs. +/// To support other schemes, a loader must be provided, which is used to +/// try to load the `.packages` file. The loader should return the contents +/// of the requestsed `.packages` file as bytes, which will be assumed to be +/// UTF-8 encoded. +Future findPackagesFromNonFile(Uri nonFileUri, + [Future> loader(Uri name)]) { + if (loader == null) loader = _httpGet; + Uri packagesFileUri = nonFileUri.resolve(".packages"); + return loader(packagesFileUri).then((List fileBytes) { + Map map = pkgfile.parse(fileBytes, packagesFileUri); + return new MapPackages(map); + }, onError: (_) { + // Didn't manage to load ".packages". Assume a "packages/" directory. + Uri packagesDirectoryUri = nonFileUri.resolve("packages/"); + return new NonFilePackagesDirectoryPackages(packagesDirectoryUri); + }); +} + +/// Fetches a file using the http library. +Future> _httpGet(Uri uri) { + return http.get(uri).then((http.Response response) { + if (response.statusCode == 200) return response.bodyBytes; + throw 0; // The error message isn't being used for anything. + }); +} diff --git a/pkgs/package_config/lib/packagemap.dart b/pkgs/package_config/lib/packagemap.dart deleted file mode 100644 index 25f27b9a2..000000000 --- a/pkgs/package_config/lib/packagemap.dart +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) 2015, 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 package_config.packagemap; - -class Packages { - static const int _EQUALS = 0x3d; - static const int _CR = 0x0d; - static const int _NL = 0x0a; - static const int _NUMBER_SIGN = 0x23; - - final Map packageMapping; - - Packages(this.packageMapping); - - /// Resolves a URI to a non-package URI. - /// - /// If [uri] is a `package:` URI, the location is resolved wrt. the - /// [packageMapping]. - /// Otherwise the original URI is returned. - Uri resolve(Uri uri) { - if (uri.scheme.toLowerCase() != "package") { - return uri; - } - if (uri.hasAuthority) { - throw new ArgumentError.value(uri, "uri", "Must not have authority"); - } - if (uri.path.startsWith("/")) { - throw new ArgumentError.value( - uri, "uri", "Path must not start with '/'."); - } - // Normalizes the path by removing '.' and '..' segments. - uri = uri.normalizePath(); - String path = uri.path; - var slashIndex = path.indexOf('/'); - String packageName; - String rest; - if (slashIndex < 0) { - packageName = path; - rest = ""; - } else { - packageName = path.substring(0, slashIndex); - rest = path.substring(slashIndex + 1); - } - Uri packageLocation = packageMapping[packageName]; - if (packageLocation == null) { - throw new ArgumentError.value( - uri, "uri", "Unknown package name: $packageName"); - } - return packageLocation.resolveUri(new Uri(path: rest)); - } - - /// Parses a `packages.cfg` file into a `Packages` object. - /// - /// The [baseLocation] is used as a base URI to resolve all relative - /// URI references against. - /// - /// The `Packages` object allows resolving package: URIs and writing - /// the mapping back to a file or string. - /// The [packageMapping] will contain a simple mapping from package name - /// to package location. - static Packages parse(String source, Uri baseLocation) { - int index = 0; - Map result = {}; - while (index < source.length) { - bool isComment = false; - int start = index; - int eqIndex = -1; - int end = source.length; - int char = source.codeUnitAt(index++); - if (char == _CR || char == _NL) { - continue; - } - if (char == _EQUALS) { - throw new FormatException("Missing package name", source, index - 1); - } - isComment = char == _NUMBER_SIGN; - while (index < source.length) { - char = source.codeUnitAt(index++); - if (char == _EQUALS && eqIndex < 0) { - eqIndex = index - 1; - } else if (char == _NL || char == _CR) { - end = index - 1; - break; - } - } - if (isComment) continue; - if (eqIndex < 0) { - throw new FormatException("No '=' on line", source, index - 1); - } - _checkIdentifier(source, start, eqIndex); - var packageName = source.substring(start, eqIndex); - - var packageLocation = Uri.parse(source, eqIndex + 1, end); - if (!packageLocation.path.endsWith('/')) { - packageLocation = - packageLocation.replace(path: packageLocation.path + "/"); - } - packageLocation = baseLocation.resolveUri(packageLocation); - if (result.containsKey(packageName)) { - throw new FormatException( - "Same package name occured twice.", source, start); - } - result[packageName] = packageLocation; - } - return new Packages(result); - } - - /** - * Writes the mapping to a [StringSink]. - * - * If [comment] is provided, the output will contain this comment - * with `#` in front of each line. - * - * If [baseUri] is provided, package locations will be made relative - * to the base URI, if possible, before writing. - */ - void write(StringSink output, {Uri baseUri, String comment}) { - if (baseUri != null && !baseUri.isAbsolute) { - throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); - } - - if (comment != null) { - for (var commentLine in comment.split('\n')) { - output.write('#'); - output.writeln(commentLine); - } - } else { - output.write("# generated by package:packagecfg at "); - output.write(new DateTime.now()); - output.writeln(); - } - - packageMapping.forEach((String packageName, Uri uri) { - // Validate packageName. - _checkIdentifier(packageName, 0, packageName.length); - output.write(packageName); - - output.write('='); - - // If baseUri provided, make uri relative. - if (baseUri != null) { - uri = relativize(uri, baseUri); - } - output.write(uri); - if (!uri.path.endsWith('/')) { - output.write('/'); - } - output.writeln(); - }); - } - - String toString() { - StringBuffer buffer = new StringBuffer(); - write(buffer); - return buffer.toString(); - } - - static Uri relativize(Uri uri, Uri baseUri) { - if (uri.hasQuery || uri.hasFragment) { - uri = new Uri( - scheme: uri.scheme, - userInfo: uri.hasAuthority ? uri.userInfo : null, - host: uri.hasAuthority ? uri.host : null, - port: uri.hasAuthority ? uri.port : null, - path: uri.path); - } - if (!baseUri.isAbsolute) { - throw new ArgumentError("Base uri '$baseUri' must be absolute."); - } - // Already relative. - if (!uri.isAbsolute) return uri; - - if (baseUri.scheme.toLowerCase() != uri.scheme.toLowerCase()) { - return uri; - } - // If authority differs, we could remove the scheme, but it's not worth it. - if (uri.hasAuthority != baseUri.hasAuthority) return uri; - if (uri.hasAuthority) { - if (uri.userInfo != baseUri.userInfo || - uri.host.toLowerCase() != baseUri.host.toLowerCase() || - uri.port != baseUri.port) { - return uri; - } - } - - baseUri = baseUri.normalizePath(); - List base = baseUri.pathSegments.toList(); - if (base.isNotEmpty) { - base = new List.from(base)..removeLast(); - } - uri = uri.normalizePath(); - List target = uri.pathSegments.toList(); - int index = 0; - while (index < base.length && index < target.length) { - if (base[index] != target[index]) { - break; - } - index++; - } - if (index == base.length) { - return new Uri(path: target.skip(index).join('/')); - } else if (index > 0) { - return new Uri( - path: '../' * (base.length - index) + target.skip(index).join('/')); - } else { - return uri; - } - } - - static bool _checkIdentifier(String string, int start, int end) { - const int a = 0x61; - const int z = 0x7a; - const int _ = 0x5f; - const int $ = 0x24; - if (start == end) return false; - for (int i = start; i < end; i++) { - var char = string.codeUnitAt(i); - if (char == _ || char == $) continue; - if ((char ^ 0x30) <= 9 && i > 0) continue; - char |= 0x20; // Lower-case letters. - if (char >= a && char <= z) continue; - throw new FormatException("Not an identifier", string, i); - } - return true; - } -} diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart new file mode 100644 index 000000000..8523ecc28 --- /dev/null +++ b/pkgs/package_config/lib/packages.dart @@ -0,0 +1,97 @@ +// Copyright (c) 2015, 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 package_config.packages; + +import "dart:async" show Future; +import "discovery.dart" show findPackages; +import "src/packages_impl.dart"; + +/// A package resolution strategy. +/// +/// Allows converting a `package:` URI to a different kind of URI. +/// +/// May also allow listing the available packages and converting +/// to a `Map` that gives the base location of each available +/// package. In some cases there is no way to find the available packages, +/// in which case [packages] and [asMap] will throw if used. +/// One such case is if the packages are resolved relative to a +/// `packages/` directory available over HTTP. +abstract class Packages { + + /// A [Packages] resolver containing no packages. + /// + /// This constant object is returned by [find] above if no + /// package resolution strategy is found. + static const Packages noPackages = const NoPackages(); + + /// Create a `Packages` object based on a map from package name to base URI. + /// + /// The resulting `Packages` object will resolve package URIs by using this + /// map. + /// There is no validation of the map containing only valid package names, + factory Packages(Map packageMapping) => + new MapPackages(packageMapping); + + /// Attempts to find a package resolution strategy for a Dart script. + /// + /// The [baseLocation] should point to a Dart script or to its directory. + /// The function goes through the following steps in order to search for + /// a packages resolution strategy: + /// + /// * First check if a `.packages` file in the script's directory. + /// If a file is found, its content is loaded and interpreted as a map + /// from package names to package location URIs. + /// If loading or parsing of the file fails, so does this function. + /// * Then if `baseLocation` is not a `file:` URI, + /// assume that a `packages/` directory exists in the script's directory, + /// and return a `Packages` object that resolves package URIs as + /// paths into that directory. + /// * If `baseLocation` is a `file:` URI, instead *check* whether + /// a `packages/` directory exists in the script directory. + /// If it does, return a `Packages` object that resolves package URIs + /// as paths into that directory. This `Packages` object is able to + /// read the directory and see which packages are available. + /// * Otherwise, check each directory in the parent path of `baseLocation` + /// for the existence of a `.packages` file. If one is found, it is loaded + /// just as in the first step. + /// * If no file is found before reaching the file system root, + /// the constant [noPacakages] is returned. It's a `Packages` object + /// with no available packages. + /// + static Future find(Uri baseLocation) => findPackages(baseLocation); + + /// Resolve a package URI into a non-package URI. + /// + /// Translates a `package:` URI, according to the package resolution + /// strategy, into a URI that can be loaded. + /// By default, only `file`, `http` and `https` URIs are returned. + /// Custom `Packages` objects may return other URIs. + /// + /// If resolution fails because a package with the requested package name + /// is not available, the [notFound] function is called. + /// If no `notFound` function is provided, it defaults to throwing an error. + /// + /// The [packageUri] must be a valid package URI. + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}); + + /// Return the names of the available packages. + /// + /// Returns an iterable that allows iterating the names of available packages. + /// + /// Some `Packages` objects are unable to find the package names, + /// and getting `packages` from such a `Packages` object will throw. + Iterable get packages; + + /// Return the names-to-base-URI mapping of the available packages. + /// + /// Returns a map from package name to a base URI. + /// The [resolve] method will resolve a package URI with a specific package + /// name to a path extending the base URI that this map gives for that + /// package name. + /// + /// Some `Packages` objects are unable to find the package names, + /// and calling `asMap` on such a `Packages` object will throw. + Map asMap(); +} diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart new file mode 100644 index 000000000..48c2334e0 --- /dev/null +++ b/pkgs/package_config/lib/packages_file.dart @@ -0,0 +1,172 @@ +// Copyright (c) 2015, 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 package_config.packages_file; + +import "package:charcode/ascii.dart"; +import "src/util.dart" show isIdentifier; + +/// Parses a `.packages` file into a map from package name to base URI. +/// +/// The [source] is the byte content of a `.packages` file, assumed to be +/// UTF-8 encoded. In practice, all sinficant parts of the file must be ASCII, +/// so Latin-1 or Windows-1252 encoding will also work fine. +/// +/// If the file content is available as a string, its [String.codeUnits] can +/// be used as the `source` argument of this function. +/// +/// The [baseLocation] is used as a base URI to resolve all relative +/// URI references against. +/// If the content was read from a file, `baseLocation` should be the +/// location of that file. +/// +/// Returns a simple mapping from package name to package location. +Map parse(List source, Uri baseLocation) { + int index = 0; + Map result = {}; + while (index < source.length) { + bool isComment = false; + int start = index; + int eqIndex = -1; + int end = source.length; + int char = source[index++]; + if (char == $cr || char == $lf) { + continue; + } + if (char == $equal) { + throw new FormatException("Missing package name", source, index - 1); + } + isComment = char == $hash; + while (index < source.length) { + char = source[index++]; + if (char == $equal && eqIndex < 0) { + eqIndex = index - 1; + } else if (char == $cr || char == $lf) { + end = index - 1; + break; + } + } + if (isComment) continue; + if (eqIndex < 0) { + throw new FormatException("No '=' on line", source, index - 1); + } + var packageName = new String.fromCharCodes(source, start, eqIndex); + if (!isIdentifier(packageName)) { + throw new FormatException("Not a valid package name", packageName, 0); + } + var packageUri = new String.fromCharCodes(source, eqIndex + 1, end); + var packageLocation = Uri.parse(packageUri); + if (!packageLocation.path.endsWith('/')) { + packageLocation = + packageLocation.replace(path: packageLocation.path + "/"); + } + packageLocation = baseLocation.resolveUri(packageLocation); + if (result.containsKey(packageName)) { + throw new FormatException( + "Same package name occured twice.", source, start); + } + result[packageName] = packageLocation; + } + return result; +} + +/// Writes the mapping to a [StringSink]. +/// +/// If [comment] is provided, the output will contain this comment +/// with `#` in front of each line. +/// +/// If [baseUri] is provided, package locations will be made relative +/// to the base URI, if possible, before writing. +void write(StringSink output, Map packageMapping, + {Uri baseUri, String comment}) { + if (baseUri != null && !baseUri.isAbsolute) { + throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); + } + + if (comment != null) { + for (var commentLine in comment.split('\n')) { + output.write('#'); + output.writeln(commentLine); + } + } else { + output.write("# generated by package:package_config at "); + output.write(new DateTime.now()); + output.writeln(); + } + + packageMapping.forEach((String packageName, Uri uri) { + // Validate packageName. + if (!isIdentifier(packageName)) { + throw new ArgumentError('"$packageName" is not a valid package name'); + } + output.write(packageName); + output.write('='); + // If baseUri provided, make uri relative. + if (baseUri != null) { + uri = _relativize(uri, baseUri); + } + output.write(uri); + if (!uri.path.endsWith('/')) { + output.write('/'); + } + output.writeln(); + }); +} + +/// Attempts to return a relative URI for [uri]. +/// +/// The result URI satisfies `baseUri.resolveUri(result) == uri`, +/// but may be relative. +/// The `baseUri` must be absolute. +Uri _relativize(Uri uri, Uri baseUri) { + assert(!baseUri.isAbsolute); + if (uri.hasQuery || uri.hasFragment) { + uri = new Uri( + scheme: uri.scheme, + userInfo: uri.hasAuthority ? uri.userInfo : null, + host: uri.hasAuthority ? uri.host : null, + port: uri.hasAuthority ? uri.port : null, + path: uri.path); + } + + // Already relative. We assume the caller knows what they are doing. + if (!uri.isAbsolute) return uri; + + if (baseUri.scheme != uri.scheme) { + return uri; + } + + // If authority differs, we could remove the scheme, but it's not worth it. + if (uri.hasAuthority != baseUri.hasAuthority) return uri; + if (uri.hasAuthority) { + if (uri.userInfo != baseUri.userInfo || + uri.host.toLowerCase() != baseUri.host.toLowerCase() || + uri.port != baseUri.port) { + return uri; + } + } + + baseUri = baseUri.normalizePath(); + List base = baseUri.pathSegments.toList(); + if (base.isNotEmpty) { + base = new List.from(base)..removeLast(); + } + uri = uri.normalizePath(); + List target = uri.pathSegments.toList(); + int index = 0; + while (index < base.length && index < target.length) { + if (base[index] != target[index]) { + break; + } + index++; + } + if (index == base.length) { + return new Uri(path: target.skip(index).join('/')); + } else if (index > 0) { + return new Uri( + path: '../' * (base.length - index) + target.skip(index).join('/')); + } else { + return uri; + } +} diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart new file mode 100644 index 000000000..612dc347d --- /dev/null +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -0,0 +1,118 @@ +// Copyright (c) 2015, 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 package_config.packages_impl; + +import "dart:collection" show UnmodifiableMapView; +import "dart:io" show Directory; +import "package:path/path.dart" as path; +import "../packages.dart"; +import "util.dart" show checkValidPackageUri; + +/// A [Packages] null-object. +class NoPackages implements Packages { + const NoPackages(); + + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { + String packageName = checkValidPackageUri(packageUri); + if (notFound != null) return notFound(packageUri); + throw new ArgumentError.value(packageUri, "packageUri", + 'No package named "$packageName"'); + } + + Iterable get packages => new Iterable.empty(); + + Map asMap() => const{}; +} + + +/// Base class for [Packages] implementations. +/// +/// This class implements the [resolve] method in terms of a private +/// member +abstract class _PackagesBase implements Packages { + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { + packageUri = packageUri.normalizePath(); + String packageName = checkValidPackageUri(packageUri); + Uri packageBase = _getBase(packageName); + if (packageBase == null) { + if (notFound != null) return notFound(packageUri); + throw new ArgumentError.value(packageUri, "packageUri", + 'No package named "$packageName"'); + } + String packagePath = packageUri.path.substring(packageName.length + 1); + return packageBase.resolve(packagePath); + } + + /// Find a base location for a package name. + /// + /// Returns `null` if no package exists with that name, and that can be + /// determined. + Uri _getBase(String packageName); +} + +/// A [Packages] implementation based on an existing map. +class MapPackages extends _PackagesBase { + final Map _mapping; + MapPackages(this._mapping); + + Uri _getBase(String packageName) => _mapping[packageName]; + + Iterable get packages => _mapping.keys; + + Map asMap() => new UnmodifiableMapView(_mapping); +} + +/// A [Packages] implementation based on a local directory. +class FilePackagesDirectoryPackages extends _PackagesBase { + final Directory _packageDir; + FilePackagesDirectoryPackages(this._packageDir); + + Uri _getBase(String packageName) => + new Uri.directory(path.join(packageName,'')); + + Iterable _listPackageNames() { + return _packageDir.listSync() + .where((e) => e is Directory) + .map((e) => path.basename(e.path)); + } + + Iterable get packages { + return _listPackageNames(); + } + + Map asMap() { + var result = {}; + for (var packageName in _listPackageNames()) { + result[packageName] = _getBase(packageName); + } + return new UnmodifiableMapView(result); + } +} + +/// A [Packages] implementation based on a remote (e.g., HTTP) directory. +/// +/// There is no way to detect which packages exist short of trying to use +/// them. You can't necessarily check whether a directory exists, +/// except by checking for a know file in the directory. +class NonFilePackagesDirectoryPackages extends _PackagesBase { + final Uri _packageBase; + NonFilePackagesDirectoryPackages(this._packageBase); + + Uri _getBase(String packageName) => _packageBase.resolve("$packageName/"); + + Error _failListingPackages() { + return new UnsupportedError( + "Cannot list packages for a ${_packageBase.scheme}: " + "based package root"); + } + + Iterable get packages { + throw _failListingPackages(); + } + + Map asMap() { + throw _failListingPackages(); + } +} diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart new file mode 100644 index 000000000..76bd1d6e5 --- /dev/null +++ b/pkgs/package_config/lib/src/util.dart @@ -0,0 +1,69 @@ +// Copyright (c) 2015, 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. + +/// Utility methods used by more than one library in the package. +library package_config.util; + +import "package:charcode/ascii.dart"; + +/// Tests whether something is a valid Dart identifier/package name. +bool isIdentifier(String string) { + if (string.isEmpty) return false; + int firstChar = string.codeUnitAt(0); + int firstCharLower = firstChar |= 0x20; + if (firstCharLower < $a || firstCharLower > $z) { + if (firstChar != $_ && firstChar != $$) return false; + } + for (int i = 1; i < string.length; i++) { + int char = string.codeUnitAt(i); + int charLower = char | 0x20; + if (charLower < $a || charLower > $z) { // Letters. + if ((char ^ 0x30) <= 9) continue; // Digits. + if (char == $_ || char == $$) continue; // $ and _ + if (firstChar != $_ && firstChar != $$) return false; + } + } + return true; +} + + +/// Validate that a Uri is a valid package:URI. +String checkValidPackageUri(Uri packageUri) { + if (packageUri.scheme != "package") { + throw new ArgumentError.value(packageUri, "packageUri", + "Not a package: URI"); + } + if (packageUri.hasAuthority) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package URIs must not have a host part"); + } + if (packageUri.hasQuery) { + // A query makes no sense if resolved to a file: URI. + throw new ArgumentError.value(packageUri, "packageUri", + "Package URIs must not have a query part"); + } + if (packageUri.hasFragment) { + // We could leave the fragment after the URL when resolving, + // but it would be odd if "package:foo/foo.dart#1" and + // "package:foo/foo.dart#2" were considered different libraries. + // Keep the syntax open in case we ever get multiple libraries in one file. + throw new ArgumentError.value(packageUri, "packageUri", + "Package URIs must not have a fragment part"); + } + if (packageUri.path.startsWith('/')) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package URIs must not start with a '/'"); + } + int firstSlash = packageUri.path.indexOf('/'); + if (firstSlash == -1) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package URIs must start with the package name followed by a '/'"); + } + String packageName = packageUri.path.substring(0, firstSlash); + if (!isIdentifier(packageName)) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package names must be valid identifiers"); + } + return packageName; +} diff --git a/pkgs/package_config/pubspec.lock b/pkgs/package_config/pubspec.lock index 197d32ed6..708d89157 100644 --- a/pkgs/package_config/pubspec.lock +++ b/pkgs/package_config/pubspec.lock @@ -13,6 +13,10 @@ packages: description: barback source: hosted version: "0.15.2+4" + charcode: + description: charcode + source: hosted + version: "1.1.0" collection: description: collection source: hosted @@ -21,6 +25,10 @@ packages: description: crypto source: hosted version: "0.9.0" + http: + description: http + source: hosted + version: "0.11.2" http_parser: description: http_parser source: hosted diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 7494fddb9..27af78ecd 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -7,5 +7,10 @@ homepage: https://github.com/dart-lang/package_config environment: sdk: '>=1.11.0-dev.0.0 <2.0.0' +dependencies: + charcode: '^1.1.0' + path: "any" + http: "any" + dev_dependencies: test: '>=0.12.0 <0.13.0' diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart index 795289cdf..310e1ee43 100644 --- a/pkgs/package_config/test/all.dart +++ b/pkgs/package_config/test/all.dart @@ -2,8 +2,8 @@ // 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. -import 'test_packagemap.dart' as packagemap; +import 'parse_test.dart' as parse; main() { - packagemap.main(); + parse.main(); } diff --git a/pkgs/package_config/test/test_packagemap.dart b/pkgs/package_config/test/parse_test.dart similarity index 60% rename from pkgs/package_config/test/test_packagemap.dart rename to pkgs/package_config/test/parse_test.dart index bce20d4b8..f7f68f10d 100644 --- a/pkgs/package_config/test/test_packagemap.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -4,61 +4,62 @@ library test_all; -import "package:package_config/packagemap.dart"; +import "package:package_config/packages.dart"; +import "package:package_config/packages_file.dart" show parse; import "package:test/test.dart"; main() { var base = Uri.parse("file:///one/two/three/packages.map"); test("empty", () { - var packages = Packages.parse(emptySample, base); - expect(packages.packageMapping, isEmpty); + var packages = doParse(emptySample, base); + expect(packages.asMap(), isEmpty); }); test("comment only", () { - var packages = Packages.parse(commentOnlySample, base); - expect(packages.packageMapping, isEmpty); + var packages = doParse(commentOnlySample, base); + expect(packages.asMap(), isEmpty); }); test("empty lines only", () { - var packages = Packages.parse(emptyLinesSample, base); - expect(packages.packageMapping, isEmpty); + var packages = doParse(emptyLinesSample, base); + expect(packages.asMap(), isEmpty); }); test("empty lines only", () { - var packages = Packages.parse(emptyLinesSample, base); - expect(packages.packageMapping, isEmpty); + var packages = doParse(emptyLinesSample, base); + expect(packages.asMap(), isEmpty); }); test("single", () { - var packages = Packages.parse(singleRelativeSample, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleRelativeSample, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("single no slash", () { - var packages = Packages.parse(singleRelativeSampleNoSlash, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleRelativeSampleNoSlash, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("single no newline", () { - var packages = Packages.parse(singleRelativeSampleNoNewline, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleRelativeSampleNoNewline, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("single absolute", () { - var packages = Packages.parse(singleAbsoluteSample, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleAbsoluteSample, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); }); test("multiple", () { - var packages = Packages.parse(multiRelativeSample, base); + var packages = doParse(multiRelativeSample, base); expect( - packages.packageMapping.keys.toList()..sort(), equals(["bar", "foo"])); + packages.packages.toList()..sort(), equals(["bar", "foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), @@ -66,51 +67,51 @@ main() { }); test("dot-dot 1", () { - var packages = Packages.parse(singleRelativeSample, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleRelativeSample, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("dot-dot 2", () { - var packages = Packages.parse(singleRelativeSample, base); - expect(packages.packageMapping.keys.toList(), equals(["foo"])); + var packages = doParse(singleRelativeSample, base); + expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("all valid chars", () { - var packages = Packages.parse(allValidCharsSample, base); - expect(packages.packageMapping.keys.toList(), equals([allValidChars])); + var packages = doParse(allValidCharsSample, base); + expect(packages.packages.toList(), equals([allValidChars])); expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); test("no escapes", () { - expect(() => Packages.parse("x%41x=x", base), throws); + expect(() => doParse("x%41x=x", base), throws); }); test("not identifiers", () { - expect(() => Packages.parse("1x=x", base), throws); - expect(() => Packages.parse(" x=x", base), throws); - expect(() => Packages.parse("\\x41x=x", base), throws); - expect(() => Packages.parse("x@x=x", base), throws); - expect(() => Packages.parse("x[x=x", base), throws); - expect(() => Packages.parse("x`x=x", base), throws); - expect(() => Packages.parse("x{x=x", base), throws); - expect(() => Packages.parse("x/x=x", base), throws); - expect(() => Packages.parse("x:x=x", base), throws); + expect(() => doParse("1x=x", base), throws); + expect(() => doParse(" x=x", base), throws); + expect(() => doParse("\\x41x=x", base), throws); + expect(() => doParse("x@x=x", base), throws); + expect(() => doParse("x[x=x", base), throws); + expect(() => doParse("x`x=x", base), throws); + expect(() => doParse("x{x=x", base), throws); + expect(() => doParse("x/x=x", base), throws); + expect(() => doParse("x:x=x", base), throws); }); test("same name twice", () { - expect(() => Packages.parse(singleRelativeSample * 2, base), throws); + expect(() => doParse(singleRelativeSample * 2, base), throws); }); for (String invalidSample in invalid) { test("invalid '$invalidSample'", () { var result; try { - result = Packages.parse(invalidSample, base); + result = doParse(invalidSample, base); } on FormatException { // expected return; @@ -120,6 +121,11 @@ main() { } } +Packages doParse(String sample, Uri baseUri) { + Map map = parse(sample.codeUnits, baseUri); + return new Packages(map); +} + // Valid samples. var emptySample = ""; var commentOnlySample = "# comment only\n"; From 8f4d9fe9f19db06c91c2163f8a6df88727e509b2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 May 2015 18:33:05 -0700 Subject: [PATCH 017/281] Revert "Revert r38549, r38552, and r38557." This reverts commit 2686535940bdbe2664d4c1bd0012988038add009. R=nweiz@google.com Review URL: https://codereview.chromium.org//1152413002 --- pkgs/pool/CHANGELOG.md | 3 + pkgs/pool/lib/pool.dart | 13 ++- pkgs/pool/pubspec.yaml | 3 +- pkgs/pool/test/pool_test.dart | 187 ++++++++++++++++++++++------------ 4 files changed, 133 insertions(+), 73 deletions(-) create mode 100644 pkgs/pool/CHANGELOG.md diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md new file mode 100644 index 000000000..e8dee50c9 --- /dev/null +++ b/pkgs/pool/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.1 + +* A `TimeoutException` is now correctly thrown if the pool detects a deadlock. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 36a29c86d..61482e3f2 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -40,14 +40,14 @@ class Pool { Timer _timer; /// The amount of time to wait before timing out the pending resources. - Duration _timeout; + final Duration _timeout; /// Creates a new pool with the given limit on how many resources may be /// allocated at once. /// /// If [timeout] is passed, then if that much time passes without any activity - /// all pending [request] futures will throw an exception. This is indented - /// to avoid deadlocks. + /// all pending [request] futures will throw a [TimeoutException]. This is + /// intended to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout; @@ -106,8 +106,11 @@ class Pool { /// emit exceptions. void _onTimeout() { for (var completer in _requestedResources) { - completer.completeError("Pool deadlock: all resources have been " - "allocated for too long.", new Chain.current()); + completer.completeError( + new TimeoutException("Pool deadlock: all resources have been " + "allocated for too long.", + _timeout), + new Chain.current()); } _requestedResources.clear(); _timer = null; diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index b6a0ff299..a7d23a52c 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,9 +1,10 @@ name: pool -version: 1.0.0 +version: 1.0.1 author: Dart Team description: A class for managing a finite pool of resources. homepage: http://github.com/dart-lang/pool dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: + fake_async: ">=0.1.0 <0.2.0" unittest: ">=0.11.0 <0.12.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index bfeb876b1..bb9e60768 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:fake_async/fake_async.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -19,30 +20,36 @@ void main() { }); test("resources block past the limit", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - expect(pool.request(), completes); - } - expect(pool.request(), doesNotComplete); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); + + async.elapse(new Duration(seconds: 1)); + }); }); test("a blocked resource is allocated when another is released", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - expect(pool.request(), completes); - } - - return pool.request().then((lastAllocatedResource) { - var blockedResource = pool.request(); - - return pumpEventQueue().then((_) { - lastAllocatedResource.release(); - return pumpEventQueue(); - }).then((_) { - expect(blockedResource, completes); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + pool.request().then((lastAllocatedResource) { + // This will only complete once [lastAllocatedResource] is released. + expect(pool.request(), completes); + + new Future.delayed(new Duration(microseconds: 1)).then((_) { + lastAllocatedResource.release(); + }); }); + + async.elapse(new Duration(seconds: 1)); }); }); }); @@ -57,63 +64,113 @@ void main() { }); test("blocks the callback past the limit", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } - pool.withResource(expectNoAsync()); + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 50; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + pool.withResource(expectNoAsync()); + + async.elapse(new Duration(seconds: 1)); + }); }); test("a blocked resource is allocated when another is released", () { - var pool = new Pool(50); - var requests = []; - for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync(() => new Completer().future)); - } + new FakeAsync().run((async) { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + pool.withResource(expectAsync(() => new Completer().future)); + } + + var completer = new Completer(); + var lastAllocatedResource = pool.withResource(() => completer.future); + var blockedResourceAllocated = false; + var blockedResource = pool.withResource(() { + blockedResourceAllocated = true; + }); - var completer = new Completer(); - var lastAllocatedResource = pool.withResource(() => completer.future); - var blockedResourceAllocated = false; - var blockedResource = pool.withResource(() { - blockedResourceAllocated = true; - }); + new Future.delayed(new Duration(microseconds: 1)).then((_) { + expect(blockedResourceAllocated, isFalse); + completer.complete(); + return new Future.delayed(new Duration(microseconds: 1)); + }).then((_) { + expect(blockedResourceAllocated, isTrue); + }); - return pumpEventQueue().then((_) { - expect(blockedResourceAllocated, isFalse); - completer.complete(); - return pumpEventQueue(); - }).then((_) { - expect(blockedResourceAllocated, isTrue); + async.elapse(new Duration(seconds: 1)); }); }); }); - // TODO(nweiz): Test timeouts when it's easier to use third-party packages. - // See r38552. -} + group("with a timeout", () { + test("doesn't time out if there are no pending requests", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } -/// Returns a [Future] that completes after pumping the event queue [times] -/// times. By default, this should pump the event queue enough times to allow -/// any code to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times = 20]) { - if (times == 0) return new Future.value(); - // We use a delayed future to allow microtask events to finish. The - // Future.value or Future() constructors use scheduleMicrotask themselves and - // would therefore not wait for microtask callbacks that are scheduled after - // invoking this method. - return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("resets the timer if a resource is returned", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + pool.request().then((lastAllocatedResource) { + // This will only complete once [lastAllocatedResource] is released. + expect(pool.request(), completes); + + new Future.delayed(new Duration(seconds: 3)).then((_) { + lastAllocatedResource.release(); + expect(pool.request(), doesNotComplete); + }); + }); + + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("resets the timer if a resource is requested", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), doesNotComplete); + + new Future.delayed(new Duration(seconds: 3)).then((_) { + expect(pool.request(), doesNotComplete); + }); + + async.elapse(new Duration(seconds: 6)); + }); + }); + + test("times out if nothing happens", () { + new FakeAsync().run((async) { + var pool = new Pool(50, timeout: new Duration(seconds: 5)); + for (var i = 0; i < 50; i++) { + expect(pool.request(), completes); + } + expect(pool.request(), throwsA(new isInstanceOf())); + + async.elapse(new Duration(seconds: 6)); + }); + }); + }); } /// Returns a function that will cause the test to fail if it's called. /// -/// This won't let the test complete until it's confident that the function -/// won't be called. +/// This should only be called within a [FakeAsync.run] zone. Function expectNoAsync() { - // Make sure the test lasts long enough for the function to get called if it's - // going to get called. - expect(pumpEventQueue(), completes); - var stack = new Trace.current(1); return () => handleExternalError( new TestFailure("Expected function not to be called."), "", @@ -122,13 +179,9 @@ Function expectNoAsync() { /// A matcher for Futures that asserts that they don't complete. /// -/// This won't let the test complete until it's confident that the function -/// won't be called. +/// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { expect(future, new isInstanceOf('Future')); - // Make sure the test lasts long enough for the function to get called if it's - // going to get called. - expect(pumpEventQueue(), completes); var stack = new Trace.current(1); future.then((_) => handleExternalError( From 3fb6e29aa46a3a77c7014b8c357d3bbf462fd0fa Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 May 2015 18:42:38 -0700 Subject: [PATCH 018/281] Fixed the homepage, upgraded to pkg/test R=nweiz@google.com Review URL: https://codereview.chromium.org//1161433002 --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/pubspec.yaml | 6 +++--- pkgs/pool/test/pool_test.dart | 28 ++++++++++------------------ 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index e8dee50c9..4fa87caec 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2 + +* Fixed the homepage. + ## 1.0.1 * A `TimeoutException` is now correctly thrown if the pool detects a deadlock. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index a7d23a52c..19aac1e54 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,10 @@ name: pool -version: 1.0.1 +version: 1.0.2 author: Dart Team description: A class for managing a finite pool of resources. -homepage: http://github.com/dart-lang/pool +homepage: https://github.com/dart-lang/pool dependencies: stack_trace: ">=0.9.2 <2.0.0" dev_dependencies: fake_async: ">=0.1.0 <0.2.0" - unittest: ">=0.11.0 <0.12.0" + test: ">=0.12.0 <0.13.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index bb9e60768..b654801e1 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -7,13 +7,12 @@ import 'dart:async'; import 'package:fake_async/fake_async.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; void main() { group("request()", () { test("resources can be requested freely up to the limit", () { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } @@ -22,7 +21,6 @@ void main() { test("resources block past the limit", () { new FakeAsync().run((async) { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } @@ -35,7 +33,6 @@ void main() { test("a blocked resource is allocated when another is released", () { new FakeAsync().run((async) { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } @@ -57,7 +54,6 @@ void main() { group("withResource()", () { test("can be called freely up to the limit", () { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 50; i++) { pool.withResource(expectAsync(() => new Completer().future)); } @@ -66,7 +62,6 @@ void main() { test("blocks the callback past the limit", () { new FakeAsync().run((async) { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 50; i++) { pool.withResource(expectAsync(() => new Completer().future)); } @@ -79,15 +74,14 @@ void main() { test("a blocked resource is allocated when another is released", () { new FakeAsync().run((async) { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 49; i++) { pool.withResource(expectAsync(() => new Completer().future)); } var completer = new Completer(); - var lastAllocatedResource = pool.withResource(() => completer.future); + pool.withResource(() => completer.future); var blockedResourceAllocated = false; - var blockedResource = pool.withResource(() { + pool.withResource(() { blockedResourceAllocated = true; }); @@ -151,7 +145,7 @@ void main() { async.elapse(new Duration(seconds: 6)); }); - }); + }); test("times out if nothing happens", () { new FakeAsync().run((async) { @@ -163,7 +157,7 @@ void main() { async.elapse(new Duration(seconds: 6)); }); - }); + }); }); } @@ -172,20 +166,18 @@ void main() { /// This should only be called within a [FakeAsync.run] zone. Function expectNoAsync() { var stack = new Trace.current(1); - return () => handleExternalError( - new TestFailure("Expected function not to be called."), "", - stack); + return () => registerException( + new TestFailure("Expected function not to be called."), stack); } /// A matcher for Futures that asserts that they don't complete. /// /// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { - expect(future, new isInstanceOf('Future')); + expect(future, new isInstanceOf()); var stack = new Trace.current(1); - future.then((_) => handleExternalError( - new TestFailure("Expected future not to complete."), "", - stack)); + future.then((_) => registerException( + new TestFailure("Expected future not to complete."), stack)); return true; }); From 86bdf0d68704a0204e29a8dcffa858529e60247c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 May 2015 19:28:28 -0700 Subject: [PATCH 019/281] fix status files TBR --- pkgs/pool/.status | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkgs/pool/.status b/pkgs/pool/.status index e9f2b0049..ff095a2f7 100644 --- a/pkgs/pool/.status +++ b/pkgs/pool/.status @@ -1,3 +1,15 @@ # Copyright (c) 2014, 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. + +# Skip non-test files ending with "_test". +packages/*: Skip +*/packages/*: Skip +*/*/packages/*: Skip +*/*/*/packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip + +# Only run tests from the build directory, since we don't care about the +# difference between transformed an untransformed code. +test/*: Skip From 2cb76b9e3c719b789acfdff9cefcea6b63425855 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 26 May 2015 11:26:32 +0200 Subject: [PATCH 020/281] Add more tests Review URL: https://codereview.chromium.org//1152173005 --- pkgs/package_config/lib/discovery.dart | 6 +- .../package_config/lib/src/packages_impl.dart | 2 +- pkgs/package_config/test/all.dart | 4 +- pkgs/package_config/test/discovery_test.dart | 281 ++++++++++++++++++ 4 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 pkgs/package_config/test/discovery_test.dart diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 78254eeba..52f208d81 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -44,9 +44,9 @@ Future findPackages( if (baseUri.scheme == "file") { return new Future.sync(() => findPackagesFromFile(baseUri)); } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, _httpGet); + return findPackagesFromNonFile(baseUri, loader: _httpGet); } else if (loader != null) { - return findPackagesFromNonFile(baseUri, loader); + return findPackagesFromNonFile(baseUri, loader: loader); } else { return new Future.value(Packages.noPackages); } @@ -138,7 +138,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// of the requestsed `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, - [Future> loader(Uri name)]) { + {Future> loader(Uri name)}) { if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List fileBytes) { diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 612dc347d..956376275 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -70,7 +70,7 @@ class FilePackagesDirectoryPackages extends _PackagesBase { FilePackagesDirectoryPackages(this._packageDir); Uri _getBase(String packageName) => - new Uri.directory(path.join(packageName,'')); + new Uri.directory(path.join(_packageDir.path, packageName, '')); Iterable _listPackageNames() { return _packageDir.listSync() diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart index 310e1ee43..79f5b3574 100644 --- a/pkgs/package_config/test/all.dart +++ b/pkgs/package_config/test/all.dart @@ -2,8 +2,10 @@ // 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. -import 'parse_test.dart' as parse; +import "discovery_test.dart" as discovery; +import "parse_test.dart" as parse; main() { parse.main(); + discovery.main(); } diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart new file mode 100644 index 000000000..4a88928e2 --- /dev/null +++ b/pkgs/package_config/test/discovery_test.dart @@ -0,0 +1,281 @@ +// Copyright (c) 2015, 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. + +import "dart:async"; +import "dart:io"; +import "package:test/test.dart"; +import "package:package_config/packages.dart"; +import "package:package_config/discovery.dart"; +import "package:path/path.dart" as path; + +const packagesFile = """ +# A comment +foo=file:///dart/packages/foo/ +bar=http://example.com/dart/packages/bar/ +baz=packages/baz/ +"""; + +void validatePackagesFile(Packages resolver, Uri location) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +} + +void validatePackagesDir(Packages resolver, Uri location) { + // Expect three packages: foo, bar and baz + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(location.resolve("packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(location.resolve("packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + if (location.scheme == "file") { + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); + } else { + expect(() => resolver.packages, throws); + } +} + + +Uri pkg(String packageName, String packagePath) { + var path; + if (packagePath.startsWith('/')) { + path = "$packageName$packagePath"; + } else { + path = "$packageName/$packagePath"; + } + return new Uri(scheme: "package", path: path); +} + +main() { + generalTest(".packages", + {".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}}}, + (Uri location) async { + Packages resolver; + resolver = await findPackages(location); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + var specificDiscovery = (location.scheme == "file") + ? findPackagesFromFile + : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesFile(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + }); + + generalTest("packages/", + {"packages": { "foo": {}, "bar": {}, "baz": {}}, + "script.dart": "main(){}"}, + (Uri location) async { + Packages resolver; + bool isFile = (location.scheme == "file"); + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + var specificDiscovery = isFile + ? findPackagesFromFile + : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesDir(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + fileTest(".packages recursive", + {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, + (Uri location) async { + Packages resolver; + resolver = await findPackages(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromFile(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = + await findPackagesFromFile(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + }); + + httpTest(".packages not recursive", + {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, + (Uri location) async { + Packages resolver; + var subdir = location.resolve("subdir/"); + resolver = await findPackages(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackages(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + }); + + fileTest("no packages", + {"script.dart": "main(){}"}, + (Uri location) async { + // A file: location with no .packages or packages returns + // Packages.noPackages. + Packages resolver; + resolver = await findPackages(location); + expect(resolver, same(Packages.noPackages)); + resolver = await findPackages(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + }); + + httpTest("no packages", + {"script.dart": "main(){}"}, + (Uri location) async { + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + test(".packages w/ loader", () async { + Uri location = Uri.parse("krutch://example.com/path/"); + Future loader(Uri file) async { + if (file.path.endsWith(".packages")) { + return packagesFile.codeUnits; + } + throw "not found"; + } + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("script.dart"), + loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader: loader); + validatePackagesFile(resolver, location); + }); + + test("no packages w/ loader", () async { + Uri location = Uri.parse("krutch://example.com/path/"); + Future loader(Uri file) async { + throw "not found"; + } + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart"), + loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader:loader); + validatePackagesDir(resolver, location); + }); +} + +/// Create a directory structure from [description] and run [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void fileTest(String name, + Map description, + Future fileTest(Uri directory)) { + group("file-test", () { + Directory tempDir = Directory.systemTemp.createTempSync("file-test"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(new Uri.directory(tempDir.path))); + }); +} + +/// HTTP-server the directory structure from [description] and run [htpTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void httpTest(String name, Map description, Future httpTest(Uri directory)) { + group("http-test", () { + var serverSub; + var uri; + setUp(() { + return HttpServer + .bind(InternetAddress.LOOPBACK_IP_V4, 0) + .then((server) { + uri = new Uri(scheme: "http", + host: "127.0.0.1", + port: server.port, + path: "/"); + serverSub = server.listen((HttpRequest request) { + // No error handling. + var path = request.uri.path; + if (path.startsWith('/')) path = path.substring(1); + if (path.endsWith('/')) path = path.substring(0, path.length - 1); + var parts = path.split('/'); + var fileOrDir = description; + for (int i = 0; i < parts.length; i++) { + fileOrDir = fileOrDir[parts[i]]; + if (fileOrDir == null) { + request.response.statusCode = 404; + request.response.close(); + } + } + request.response.write(fileOrDir); + request.response.close(); + }); + }); + }); + tearDown(() => serverSub.cancel()); + test(name, () => httpTest(uri)); + }); +} + +void generalTest(String name, Map description, Future action(Uri location)) { + fileTest(name, description, action); + httpTest(name, description, action); +} + +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + if (content is Map) { + Directory subDir = new Directory(path.join(target.path, name)); + subDir.createSync(); + _createFiles(subDir, content); + } else { + File file = new File(path.join(target.path, name)); + file.writeAsStringSync(content, flush: true); + } + }); +} + + From f3bbc021c17b6b70a2d772d5976c9a76e1be7438 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Tue, 26 May 2015 12:48:53 -0700 Subject: [PATCH 021/281] Badge update. (Fix dart-lang/package_config#7.) --- pkgs/package_config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 140c3c4f9..1437e31c1 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,7 +4,7 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg)](https://travis-ci.org/dart-lang/linter) +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg)](https://travis-ci.org/dart-lang/package_config) ## Features and bugs From 45aa4d5882b64c3b5b2602c50fd17eda39f25e9b Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Tue, 26 May 2015 12:50:09 -0700 Subject: [PATCH 022/281] Travis badge teak (point to master). --- pkgs/package_config/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 1437e31c1..42ae1e99b 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,8 +4,7 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg)](https://travis-ci.org/dart-lang/package_config) - +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) ## Features and bugs From 3c2c5f5434f021d98c0524eaaa2c435ba8693700 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 27 May 2015 12:46:11 -0700 Subject: [PATCH 023/281] Update travis.sh --- pkgs/package_config/tool/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/tool/travis.sh b/pkgs/package_config/tool/travis.sh index 82423816b..6d8cfe375 100755 --- a/pkgs/package_config/tool/travis.sh +++ b/pkgs/package_config/tool/travis.sh @@ -9,7 +9,7 @@ set -e # Verify that the libraries are error free. dartanalyzer --fatal-warnings \ - lib/packagemap.dart \ + lib/packages.dart \ test/all.dart # Run the tests. From 385d634284979e23f127b376c190fc5463cce761 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 27 May 2015 13:01:50 -0700 Subject: [PATCH 024/281] Build fix. [TBR] (Fix dart-lang/package_config#9) --- pkgs/package_config/lib/src/packages_impl.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 956376275..6d88a65a0 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -21,7 +21,7 @@ class NoPackages implements Packages { 'No package named "$packageName"'); } - Iterable get packages => new Iterable.empty(); + Iterable get packages => new Iterable.generate(0); Map asMap() => const{}; } From fd1d37d5ba2e444804436148025fe814824f124c Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 28 May 2015 10:00:52 -0700 Subject: [PATCH 025/281] Version bump. Bump to tag package discovery logic. --- pkgs/package_config/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 27af78ecd..36daf6f84 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.1 +version: 0.0.2 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config @@ -9,8 +9,8 @@ environment: dependencies: charcode: '^1.1.0' - path: "any" - http: "any" + path: 'any' + http: 'any' dev_dependencies: test: '>=0.12.0 <0.13.0' From 860fa65be9122e4c2e73f11437ef21968726a26a Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 28 May 2015 10:09:50 -0700 Subject: [PATCH 026/281] Constraint cleanup. --- pkgs/package_config/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 36daf6f84..0efb23f22 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: charcode: '^1.1.0' - path: 'any' - http: 'any' + http: '^0.11.2' + path: '>=1.0.0 <2.0.0' dev_dependencies: test: '>=0.12.0 <0.13.0' From 2e49f23243aba94882c4ecce75ca6aaadfe4daa8 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 28 May 2015 10:55:08 -0700 Subject: [PATCH 027/281] Package badge. --- pkgs/package_config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 42ae1e99b..9a0995d6b 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,7 +4,7 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](http://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) ## Features and bugs From 58cc2fe7943ad73cd61d323b02e3198715dfe994 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 28 May 2015 13:06:55 -0700 Subject: [PATCH 028/281] Widen http version constraint. (Required for constraint solving in the SDK build.) --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 0efb23f22..4a3123e6d 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: charcode: '^1.1.0' - http: '^0.11.2' + http: '^0.11.0' path: '>=1.0.0 <2.0.0' dev_dependencies: From f04393798e722151745e8cf2f3126e20531f8bd4 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 28 May 2015 13:08:20 -0700 Subject: [PATCH 029/281] Update pubspec.yaml --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 4a3123e6d..5bda6ffae 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.2 +version: 0.0.2+1 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From ffabb77477e3f6cf27c8e0af354a01a7f6a3b7e0 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 28 May 2015 13:36:25 -0700 Subject: [PATCH 030/281] Inline normalizePath to make observatory happy. --- pkgs/package_config/lib/packages_file.dart | 7 +++++-- pkgs/package_config/lib/src/packages_impl.dart | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 48c2334e0..03b37b649 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -147,12 +147,12 @@ Uri _relativize(Uri uri, Uri baseUri) { } } - baseUri = baseUri.normalizePath(); + baseUri = _normalizePath(baseUri); List base = baseUri.pathSegments.toList(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } - uri = uri.normalizePath(); + uri = _normalizePath(uri); List target = uri.pathSegments.toList(); int index = 0; while (index < base.length && index < target.length) { @@ -170,3 +170,6 @@ Uri _relativize(Uri uri, Uri baseUri) { return uri; } } + +// TODO: inline to uri.normalizePath() when we move to 1.11 +Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 6d88a65a0..880b9db1f 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -33,7 +33,7 @@ class NoPackages implements Packages { /// member abstract class _PackagesBase implements Packages { Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - packageUri = packageUri.normalizePath(); + packageUri = _normalizePath(packageUri); String packageName = checkValidPackageUri(packageUri); Uri packageBase = _getBase(packageName); if (packageBase == null) { @@ -50,6 +50,9 @@ abstract class _PackagesBase implements Packages { /// Returns `null` if no package exists with that name, and that can be /// determined. Uri _getBase(String packageName); + + // TODO: inline to uri.normalizePath() when we move to 1.11 + static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); } /// A [Packages] implementation based on an existing map. From a7722c1554c8208f6896feb4046340e98d109061 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 28 May 2015 13:38:18 -0700 Subject: [PATCH 031/281] Version bump. --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5bda6ffae..20494b9f6 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.2+1 +version: 0.0.2+2 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From de64d3dd23f9ff40b4d165d9c984ddb45dfd6ab0 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Thu, 28 May 2015 15:58:43 -0700 Subject: [PATCH 032/281] Don't use Uri.directory --- pkgs/package_config/lib/discovery.dart | 4 ++-- pkgs/package_config/lib/packages.dart | 2 +- pkgs/package_config/lib/packages_file.dart | 2 +- pkgs/package_config/lib/src/packages_impl.dart | 6 +++--- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 52f208d81..f298a0afe 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -101,7 +101,7 @@ FileSystemEntity _findPackagesFile(String workingDirectory) { /// a `packages/` directory in the same place. /// If that also fails, it starts checking parent directories for a `.packages` /// file, and stops if it finds it. -/// Otherwise it gives up and returns [Pacakges.noPackages]. +/// Otherwise it gives up and returns [Packages.noPackages]. Packages findPackagesFromFile(Uri fileBaseUri) { Uri baseDirectoryUri = fileBaseUri; if (!fileBaseUri.path.endsWith('/')) { @@ -135,7 +135,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// By default, this function only works for `http:` and `https:` URIs. /// To support other schemes, a loader must be provided, which is used to /// try to load the `.packages` file. The loader should return the contents -/// of the requestsed `.packages` file as bytes, which will be assumed to be +/// of the requested `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, {Future> loader(Uri name)}) { diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart index 8523ecc28..3fba062f5 100644 --- a/pkgs/package_config/lib/packages.dart +++ b/pkgs/package_config/lib/packages.dart @@ -57,7 +57,7 @@ abstract class Packages { /// for the existence of a `.packages` file. If one is found, it is loaded /// just as in the first step. /// * If no file is found before reaching the file system root, - /// the constant [noPacakages] is returned. It's a `Packages` object + /// the constant [noPackages] is returned. It's a `Packages` object /// with no available packages. /// static Future find(Uri baseLocation) => findPackages(baseLocation); diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 03b37b649..2228cb3f0 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -10,7 +10,7 @@ import "src/util.dart" show isIdentifier; /// Parses a `.packages` file into a map from package name to base URI. /// /// The [source] is the byte content of a `.packages` file, assumed to be -/// UTF-8 encoded. In practice, all sinficant parts of the file must be ASCII, +/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII, /// so Latin-1 or Windows-1252 encoding will also work fine. /// /// If the file content is available as a string, its [String.codeUnits] can diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 880b9db1f..645d76525 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -50,9 +50,9 @@ abstract class _PackagesBase implements Packages { /// Returns `null` if no package exists with that name, and that can be /// determined. Uri _getBase(String packageName); - + // TODO: inline to uri.normalizePath() when we move to 1.11 - static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); + static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); } /// A [Packages] implementation based on an existing map. @@ -73,7 +73,7 @@ class FilePackagesDirectoryPackages extends _PackagesBase { FilePackagesDirectoryPackages(this._packageDir); Uri _getBase(String packageName) => - new Uri.directory(path.join(_packageDir.path, packageName, '')); + new Uri.file(path.join(_packageDir.path, packageName, '.')); Iterable _listPackageNames() { return _packageDir.listSync() diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 20494b9f6..2a84d20c4 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.2+2 +version: 0.0.2+3 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 4a88928e2..16bdd267b 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -215,7 +215,7 @@ void fileTest(String name, tearDown(() { tempDir.deleteSync(recursive: true); }); - test(name, () => fileTest(new Uri.directory(tempDir.path))); + test(name, () => fileTest(new Uri.file(path.join(tempDir.path, ".")))); }); } From 95ebf31911fe8621cddbd3d504535f7c77c04eb3 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Thu, 28 May 2015 18:04:07 -0700 Subject: [PATCH 033/281] Allow "_" as the first char in a package name --- pkgs/package_config/lib/src/util.dart | 2 +- pkgs/package_config/test/discovery_test.dart | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 76bd1d6e5..abf1d52f0 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -11,7 +11,7 @@ import "package:charcode/ascii.dart"; bool isIdentifier(String string) { if (string.isEmpty) return false; int firstChar = string.codeUnitAt(0); - int firstCharLower = firstChar |= 0x20; + int firstCharLower = firstChar | 0x20; if (firstCharLower < $a || firstCharLower > $z) { if (firstChar != $_ && firstChar != $$) return false; } diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 16bdd267b..16544e43d 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -93,6 +93,14 @@ main() { validatePackagesDir(resolver, location); }); + generalTest("underscore packages", + {"packages": {"_foo": {}}}, + (Uri location) async { + Packages resolver = await findPackages(location); + expect(resolver.resolve(pkg("_foo", "foo.dart")), + equals(location.resolve("packages/_foo/foo.dart"))); + }); + fileTest(".packages recursive", {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, (Uri location) async { From 8fee1b417ab070010ca15dd619cc462a01443f53 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Fri, 29 May 2015 09:58:04 -0700 Subject: [PATCH 034/281] Bump version to 0.0.2+4 --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 2a84d20c4..aca9c836c 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.2+3 +version: 0.0.2+4 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 8de7c1064f9f124d520479f2a8be6b64507d399b Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Fri, 29 May 2015 09:58:04 -0700 Subject: [PATCH 035/281] Separate out VM dependencies. The Packages interface class should not depend on a platform specific library (dart:io). This removed the dependency, and also splits the implementation classes into those that are generally applicable and those that requite dart:io to operate (the "local packages directory" which allows iterating the package names by scanning the directory). Bump version to 0.0.2+4 --- pkgs/package_config/lib/discovery.dart | 1 + pkgs/package_config/lib/packages.dart | 38 --------------- .../package_config/lib/src/packages_impl.dart | 47 ++++--------------- .../lib/src/packages_io_impl.dart | 37 +++++++++++++++ pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/parse_test.dart | 3 +- 6 files changed, 51 insertions(+), 77 deletions(-) create mode 100644 pkgs/package_config/lib/src/packages_io_impl.dart diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index f298a0afe..f8e45d491 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -11,6 +11,7 @@ import "package:http/http.dart" as http; import "packages.dart"; import "packages_file.dart" as pkgfile show parse; import "src/packages_impl.dart"; +import "src/packages_io_impl.dart"; /// Discover the package configuration for a Dart script. /// diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart index 3fba062f5..dbaa06dfd 100644 --- a/pkgs/package_config/lib/packages.dart +++ b/pkgs/package_config/lib/packages.dart @@ -4,8 +4,6 @@ library package_config.packages; -import "dart:async" show Future; -import "discovery.dart" show findPackages; import "src/packages_impl.dart"; /// A package resolution strategy. @@ -26,42 +24,6 @@ abstract class Packages { /// package resolution strategy is found. static const Packages noPackages = const NoPackages(); - /// Create a `Packages` object based on a map from package name to base URI. - /// - /// The resulting `Packages` object will resolve package URIs by using this - /// map. - /// There is no validation of the map containing only valid package names, - factory Packages(Map packageMapping) => - new MapPackages(packageMapping); - - /// Attempts to find a package resolution strategy for a Dart script. - /// - /// The [baseLocation] should point to a Dart script or to its directory. - /// The function goes through the following steps in order to search for - /// a packages resolution strategy: - /// - /// * First check if a `.packages` file in the script's directory. - /// If a file is found, its content is loaded and interpreted as a map - /// from package names to package location URIs. - /// If loading or parsing of the file fails, so does this function. - /// * Then if `baseLocation` is not a `file:` URI, - /// assume that a `packages/` directory exists in the script's directory, - /// and return a `Packages` object that resolves package URIs as - /// paths into that directory. - /// * If `baseLocation` is a `file:` URI, instead *check* whether - /// a `packages/` directory exists in the script directory. - /// If it does, return a `Packages` object that resolves package URIs - /// as paths into that directory. This `Packages` object is able to - /// read the directory and see which packages are available. - /// * Otherwise, check each directory in the parent path of `baseLocation` - /// for the existence of a `.packages` file. If one is found, it is loaded - /// just as in the first step. - /// * If no file is found before reaching the file system root, - /// the constant [noPackages] is returned. It's a `Packages` object - /// with no available packages. - /// - static Future find(Uri baseLocation) => findPackages(baseLocation); - /// Resolve a package URI into a non-package URI. /// /// Translates a `package:` URI, according to the package resolution diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index 645d76525..e85f75581 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -2,11 +2,12 @@ // 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. +/// Implementations of [Packages] that may be used in either server or browser +/// based applications. For implementations that can only run in the browser, +/// see [package_config.packages_io_impl]. library package_config.packages_impl; import "dart:collection" show UnmodifiableMapView; -import "dart:io" show Directory; -import "package:path/path.dart" as path; import "../packages.dart"; import "util.dart" show checkValidPackageUri; @@ -26,16 +27,15 @@ class NoPackages implements Packages { Map asMap() => const{}; } - /// Base class for [Packages] implementations. /// /// This class implements the [resolve] method in terms of a private /// member -abstract class _PackagesBase implements Packages { +abstract class PackagesBase implements Packages { Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { packageUri = _normalizePath(packageUri); String packageName = checkValidPackageUri(packageUri); - Uri packageBase = _getBase(packageName); + Uri packageBase = getBase(packageName); if (packageBase == null) { if (notFound != null) return notFound(packageUri); throw new ArgumentError.value(packageUri, "packageUri", @@ -49,61 +49,34 @@ abstract class _PackagesBase implements Packages { /// /// Returns `null` if no package exists with that name, and that can be /// determined. - Uri _getBase(String packageName); + Uri getBase(String packageName); // TODO: inline to uri.normalizePath() when we move to 1.11 static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); } /// A [Packages] implementation based on an existing map. -class MapPackages extends _PackagesBase { +class MapPackages extends PackagesBase { final Map _mapping; MapPackages(this._mapping); - Uri _getBase(String packageName) => _mapping[packageName]; + Uri getBase(String packageName) => _mapping[packageName]; Iterable get packages => _mapping.keys; Map asMap() => new UnmodifiableMapView(_mapping); } -/// A [Packages] implementation based on a local directory. -class FilePackagesDirectoryPackages extends _PackagesBase { - final Directory _packageDir; - FilePackagesDirectoryPackages(this._packageDir); - - Uri _getBase(String packageName) => - new Uri.file(path.join(_packageDir.path, packageName, '.')); - - Iterable _listPackageNames() { - return _packageDir.listSync() - .where((e) => e is Directory) - .map((e) => path.basename(e.path)); - } - - Iterable get packages { - return _listPackageNames(); - } - - Map asMap() { - var result = {}; - for (var packageName in _listPackageNames()) { - result[packageName] = _getBase(packageName); - } - return new UnmodifiableMapView(result); - } -} - /// A [Packages] implementation based on a remote (e.g., HTTP) directory. /// /// There is no way to detect which packages exist short of trying to use /// them. You can't necessarily check whether a directory exists, /// except by checking for a know file in the directory. -class NonFilePackagesDirectoryPackages extends _PackagesBase { +class NonFilePackagesDirectoryPackages extends PackagesBase { final Uri _packageBase; NonFilePackagesDirectoryPackages(this._packageBase); - Uri _getBase(String packageName) => _packageBase.resolve("$packageName/"); + Uri getBase(String packageName) => _packageBase.resolve("$packageName/"); Error _failListingPackages() { return new UnsupportedError( diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart new file mode 100644 index 000000000..21b61fdab --- /dev/null +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2015, 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. + +/// Implementations of [Packages] that can only be used in server based +/// applications. +library package_config.packages_io_impl; + +import "dart:collection" show UnmodifiableMapView; +import "dart:io" show Directory; +import "package:path/path.dart" as path; +import "packages_impl.dart"; + +/// A [Packages] implementation based on a local directory. +class FilePackagesDirectoryPackages extends PackagesBase { + final Directory _packageDir; + FilePackagesDirectoryPackages(this._packageDir); + + Uri getBase(String packageName) => + new Uri.file(path.join(_packageDir.path, packageName, '.')); + + Iterable _listPackageNames() { + return _packageDir.listSync() + .where((e) => e is Directory) + .map((e) => path.basename(e.path)); + } + + Iterable get packages => _listPackageNames(); + + Map asMap() { + var result = {}; + for (var packageName in _listPackageNames()) { + result[packageName] = getBase(packageName); + } + return new UnmodifiableMapView(result); + } +} diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index aca9c836c..338aab5bf 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.2+4 +version: 0.0.3 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index f7f68f10d..ddd8ff6ca 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -6,6 +6,7 @@ library test_all; import "package:package_config/packages.dart"; import "package:package_config/packages_file.dart" show parse; +import "package:package_config/src/packages_impl.dart"; import "package:test/test.dart"; main() { @@ -123,7 +124,7 @@ main() { Packages doParse(String sample, Uri baseUri) { Map map = parse(sample.codeUnits, baseUri); - return new Packages(map); + return new MapPackages(map); } // Valid samples. From b3a31b68e0b61e0546f2448ec34f2118305b91d8 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Thu, 4 Jun 2015 13:50:22 -0700 Subject: [PATCH 036/281] Remove dependency on http package BUG= Review URL: https://codereview.appspot.com/243950044 --- pkgs/package_config/lib/discovery.dart | 42 +++++++++++++++++++------- pkgs/package_config/pubspec.lock | 4 --- pkgs/package_config/pubspec.yaml | 3 +- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index f8e45d491..0dd7f5508 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -5,9 +5,11 @@ library package_config.discovery; import "dart:async"; -import "dart:io" show Directory, File, FileSystemEntity; +import "dart:io"; +import "dart:typed_data" show Uint8List; + import "package:path/path.dart" as path; -import "package:http/http.dart" as http; + import "packages.dart"; import "packages_file.dart" as pkgfile show parse; import "src/packages_impl.dart"; @@ -39,8 +41,7 @@ import "src/packages_io_impl.dart"; /// It must return the *contents* of the file identified by the URI it's given, /// which should be a UTF-8 encoded `.packages` file, and must return an /// error future if loading fails for any reason. -Future findPackages( - Uri baseUri, +Future findPackages(Uri baseUri, {Future> loader(Uri unsupportedUri)}) { if (baseUri.scheme == "file") { return new Future.sync(() => findPackagesFromFile(baseUri)); @@ -113,8 +114,8 @@ Packages findPackagesFromFile(Uri fileBaseUri) { if (location == null) return Packages.noPackages; if (location is File) { List fileBytes = location.readAsBytesSync(); - Map map = pkgfile.parse(fileBytes, - new Uri.file(location.path)); + Map map = + pkgfile.parse(fileBytes, new Uri.file(location.path)); return new MapPackages(map); } assert(location is Directory); @@ -139,7 +140,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// of the requested `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) { + {Future> loader(Uri name)}) { if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List fileBytes) { @@ -152,10 +153,29 @@ Future findPackagesFromNonFile(Uri nonFileUri, }); } -/// Fetches a file using the http library. +/// Fetches a file over http. Future> _httpGet(Uri uri) { - return http.get(uri).then((http.Response response) { - if (response.statusCode == 200) return response.bodyBytes; - throw 0; // The error message isn't being used for anything. + HttpClient client = new HttpClient(); + return client + .getUrl(uri) + .then((HttpClientRequest request) => request.close()) + .then((HttpClientResponse response) { + if (response.statusCode != HttpStatus.OK) { + String msg = 'Failure getting $uri: ' + '${response.statusCode} ${response.reasonPhrase}'; + throw msg; + } + return response.toList(); + }).then((List> splitContent) { + int totalLength = splitContent.fold(0, (int old, List list) { + return old + list.length; + }); + Uint8List result = new Uint8List(totalLength); + int offset = 0; + for (List contentPart in splitContent) { + result.setRange(offset, offset + contentPart.length, contentPart); + offset += contentPart.length; + } + return result; }); } diff --git a/pkgs/package_config/pubspec.lock b/pkgs/package_config/pubspec.lock index 708d89157..5cae00509 100644 --- a/pkgs/package_config/pubspec.lock +++ b/pkgs/package_config/pubspec.lock @@ -25,10 +25,6 @@ packages: description: crypto source: hosted version: "0.9.0" - http: - description: http - source: hosted - version: "0.11.2" http_parser: description: http_parser source: hosted diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 338aab5bf..5eca33065 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.3 +version: 0.0.3+1 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config @@ -9,7 +9,6 @@ environment: dependencies: charcode: '^1.1.0' - http: '^0.11.0' path: '>=1.0.0 <2.0.0' dev_dependencies: From 53cf751c437cf72d51211e1a5b7a3643e86c66b2 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 10 Jun 2015 09:27:28 +0200 Subject: [PATCH 037/281] Initial approach to discovering package resolution for directory tree. R=brianwilkerson@google.com, pquitslund@google.com Review URL: https://codereview.chromium.org//1169513002. --- .../lib/discovery_analysis.dart | 167 ++++++++++++++++++ pkgs/package_config/pubspec.yaml | 2 +- .../test/discovery_analysis_test.dart | 122 +++++++++++++ 3 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 pkgs/package_config/lib/discovery_analysis.dart create mode 100644 pkgs/package_config/test/discovery_analysis_test.dart diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart new file mode 100644 index 000000000..f3bcac68e --- /dev/null +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -0,0 +1,167 @@ +// Copyright (c) 2015, 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. + +/// Analyse a directory structure and find packages resolvers for each +/// sub-directory. +/// +/// The resolvers are generally the same that would be found by using +/// the `discovery.dart` library on each sub-directory in turn, +/// but more efficiently and with some heuristics for directories that +/// wouldn't otherwise have a package resolution strategy, or that are +/// determined to be "package directories" themselves. +library package_config.discovery_analysis; + +import "dart:io" show File, Directory; +import "dart:collection" show HashMap; + +import "package:path/path.dart" as path; + +import "packages.dart"; +import "discovery.dart"; +import "packages_file.dart" as pkgfile; +import "src/packages_impl.dart"; +import "src/packages_io_impl.dart"; + +/// Associates a [Packages] package resolution strategy with a directory. +/// +/// The package resolution applies to the directory and any sub-directory +/// that doesn't have its own overriding child [PackageContext]. +abstract class PackageContext { + /// The directory that introduced the [packages] resolver. + Directory get directory; + + /// A [Packages] resolver that applies to the directory. + /// + /// Introduced either by a `.packages` file or a `packages/` directory. + Packages get packages; + + /// Child contexts that apply to sub-directories of [directory]. + List get children; + + /// Look up the [PackageContext] that applies to a specific directory. + /// + /// The directory must be inside [directory]. + PackageContext operator[](Directory directory); + + /// A map from directory to package resolver. + /// + /// Has an entry for this package context and for each child context + /// contained in this one. + Map asMap(); + + /// Analyze [directory] and sub-directories for package resolution strategies. + /// + /// Returns a mapping from sub-directories to [Packages] objects. + /// + /// The analysis assumes that there are no `.packages` files in a parent + /// directory of `directory`. If there is, its corresponding `Packages` object + /// should be provided as `root`. + static PackageContext findAll(Directory directory, + {Packages root: Packages.noPackages}) { + if (!directory.existsSync()) { + throw new ArgumentError("Directory not found: $directory"); + } + List contexts = []; + void findRoots(Directory directory) { + Packages packages; + List oldContexts; + File packagesFile = new File(path.join(directory.path, ".packages")); + if (packagesFile.existsSync()) { + packages = _loadPackagesFile(packagesFile); + oldContexts = contexts; + contexts = []; + } else { + Directory packagesDir = + new Directory(path.join(directory.path, "packages")); + if (packagesDir.existsSync()) { + packages = new FilePackagesDirectoryPackages(packagesDir); + oldContexts = contexts; + contexts = []; + } + } + for (var entry in directory.listSync()) { + if (entry is Directory) { + if (packages == null || !entry.path.endsWith("/packages")) { + findRoots(entry); + } + } + } + if (packages != null) { + oldContexts.add(new _PackageContext(directory, packages, contexts)); + contexts = oldContexts; + } + } + findRoots(directory); + // If the root is not itself context root, add a the wrapper context. + if (contexts.length == 1 && + contexts[0].directory == directory) { + return contexts[0]; + } + return new _PackageContext(directory, root, contexts); + } +} + +class _PackageContext implements PackageContext { + final Directory directory; + final Packages packages; + final List children; + _PackageContext(this.directory, this.packages, List children) + : children = new List.unmodifiable(children); + + Map asMap() { + var result = new HashMap(); + recurse(_PackageContext current) { + result[current.directory] = current.packages; + for (var child in current.children) { + recurse(child); + } + } + recurse(this); + return result; + } + + PackageContext operator[](Directory directory) { + String path = directory.path; + if (!path.startsWith(this.directory.path)) { + throw new ArgumentError("Not inside $path: $directory"); + } + _PackageContext current = this; + // The current path is know to agree with directory until deltaIndex. + int deltaIndex = current.directory.path.length; + List children = current.children; + int i = 0; + while (i < children.length) { + // TODO(lrn): Sort children and use binary search. + _PackageContext child = children[i]; + String childPath = child.directory.path; + if (_stringsAgree(path, childPath, deltaIndex, childPath.length)) { + deltaIndex = childPath.length; + if (deltaIndex == path.length) { + return child; + } + current = child; + children = current.children; + i = 0; + continue; + } + i++; + } + return current; + } + + static bool _stringsAgree(String a, String b, int start, int end) { + if (a.length < end || b.length < end) return false; + for (int i = start; i < end; i++) { + if (a.codeUnitAt(i) != b.codeUnitAt(i)) return false; + } + return true; + } +} + +Packages _loadPackagesFile(File file) { + var uri = new Uri.file(file.path); + var bytes = file.readAsBytesSync(); + var map = pkgfile.parse(bytes, uri); + return new MapPackages(map); +} diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5eca33065..0f2735b53 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.3+1 +version: 0.0.4 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart new file mode 100644 index 000000000..ad007c073 --- /dev/null +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -0,0 +1,122 @@ +// Copyright (c) 2015, 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. + +import "dart:async"; +import "dart:io"; + +import "package:package_config/discovery_analysis.dart"; +import "package:package_config/packages.dart"; +import "package:path/path.dart" as path; +import "package:test/test.dart"; + +main() { + fileTest("basic", + {".packages": packagesFile, + "foo": {".packages": packagesFile}, + "bar": {"packages": {"foo": {}, "bar":{}, "baz": {}}}, + "baz": {}}, + (Directory directory) { + var dirUri = new Uri.directory(directory.path); + PackageContext ctx = PackageContext.findAll(directory); + PackagesContext root = ctx[directory]; + expect(root, same(ctx)); + validatePackagesFile(root.packages, dirUri); + var fooDir = sub(directory, "foo"); + PackagesContext foo = ctx[fooDir]; + expect(identical(root, foo), isFalse); + validatePackagesFile(foo.packages, dirUri.resolve("foo/")); + var barDir = sub(directory, "bar"); + PackagesContext bar = ctx[sub(directory, "bar")]; + validatePackagesDir(bar.packages, dirUri.resolve("bar/")); + PackagesContext barbar = ctx[sub(barDir, "bar")]; + expect(barbar, same(bar)); // inherited. + PackagesContext baz = ctx[sub(directory, "baz")]; + expect(baz, same(root)); // inherited. + + var map = ctx.asMap(); + expect(map.keys.map((dir) => dir.path), + unorderedEquals([directory.path, fooDir.path, barDir.path])); + }); +} + +Directory sub(Directory parent, String dirName) { + return new Directory(path.join(parent.path, dirName)); +} + +const packagesFile = """ +# A comment +foo=file:///dart/packages/foo/ +bar=http://example.com/dart/packages/bar/ +baz=packages/baz/ +"""; + +void validatePackagesFile(Packages resolver, Uri location) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +} + +void validatePackagesDir(Packages resolver, Uri location) { + // Expect three packages: foo, bar and baz + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(location.resolve("packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(location.resolve("packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + if (location.scheme == "file") { + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); + } else { + expect(() => resolver.packages, throws); + } +} + +Uri pkg(String packageName, String packagePath) { + var path; + if (packagePath.startsWith('/')) { + path = "$packageName$packagePath"; + } else { + path = "$packageName/$packagePath"; + } + return new Uri(scheme: "package", path: path); +} + +/// Create a directory structure from [description] and run [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void fileTest(String name, + Map description, + Future fileTest(Uri directory)) { + group("file-test", () { + Directory tempDir = Directory.systemTemp.createTempSync("file-test"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(tempDir)); + }); +} + +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + if (content is Map) { + Directory subDir = new Directory(path.join(target.path, name)); + subDir.createSync(); + _createFiles(subDir, content); + } else { + File file = new File(path.join(target.path, name)); + file.writeAsStringSync(content, flush: true); + } + }); +} From 3fcadf72678f524f6d632c80b643519e5d90cd07 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 10 Jun 2015 09:43:56 +0200 Subject: [PATCH 038/281] Add functions to help with --packages/--package-root command line parameters. R=pquitslund@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//1166443005. --- pkgs/package_config/lib/discovery.dart | 96 ++++++++++++-------- pkgs/package_config/test/discovery_test.dart | 48 +++++++++- 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 0dd7f5508..35c3ece7f 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -15,6 +15,55 @@ import "packages_file.dart" as pkgfile show parse; import "src/packages_impl.dart"; import "src/packages_io_impl.dart"; +/// Reads a package resolution file and creates a [Packages] object from it. +/// +/// The [packagesFile] must exist and be loadable. +/// Currently that means the URI must have a `file`, `http` or `https` scheme, +/// and that the file can be loaded and its contents parsed correctly. +/// +/// If the [loader] is provided, it is used to fetch non-`file` URIs, and +/// it can support other schemes or set up more complex HTTP requests. +/// +/// This function can be used to load an explicitly configured package +/// resolution file, for example one specified using a `--packages` +/// command-line parameter. +Future loadPackagesFile(Uri packagesFile, + {Future> loader(Uri uri)}) { + Packages parseBytes(List bytes) { + Map packageMap = pkgfile.parse(bytes, packagesFile); + return new MapPackages(packageMap); + } + if (packagesFile.scheme == "file") { + File file = new File.fromUri(packagesFile); + return file.readAsBytes().then(parseBytes); + } + if (loader == null) { + return http.readBytes(packagesFile).then(parseBytes); + } + return loader(packagesFile).then(parseBytes); +} + + +/// Create a [Packages] object for a package directory. +/// +/// The [packagesDir] URI should refer to a directory. +/// Package names are resolved as relative to sub-directories of the +/// package directory. +/// +/// This function can be used for explicitly configured package directories, +/// for example one specified using a `--package-root` comand-line parameter. +Packages getPackagesDirectory(Uri packagesDir) { + if (packagesDir.scheme == "file") { + Directory directory = new Directory.fromUri(packagesDir); + return new FilePackagesDirectoryPackages(directory); + } + if (!packagesDir.path.endsWith('/')) { + packagesDir = packagesDir.replace(path: packagesDir.path + '/'); + } + return new NonFilePackagesDirectoryPackages(packagesDir); +} + + /// Discover the package configuration for a Dart script. /// /// The [baseUri] points to either the Dart script or its directory. @@ -36,19 +85,21 @@ import "src/packages_io_impl.dart"; /// It needs to be able to load a `.packages` file from the URI, so only /// recognized schemes are accepted. /// -/// To support other schemes, an optional [loader] function can be supplied. -/// It's called to load the `.packages` file for any unsupported scheme. -/// It must return the *contents* of the file identified by the URI it's given, -/// which should be a UTF-8 encoded `.packages` file, and must return an +/// To support other schemes, or more complex HTTP requests, +/// an optional [loader] function can be supplied. +/// It's called to load the `.packages` file for a non-`file` scheme. +/// The loader function returns the *contents* of the file +/// identified by the URI it's given. +/// The content should be a UTF-8 encoded `.packages` file, and must return an /// error future if loading fails for any reason. Future findPackages(Uri baseUri, - {Future> loader(Uri unsupportedUri)}) { + {Future> loader(Uri unsupportedUri)}) { if (baseUri.scheme == "file") { return new Future.sync(() => findPackagesFromFile(baseUri)); - } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, loader: _httpGet); } else if (loader != null) { return findPackagesFromNonFile(baseUri, loader: loader); + } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { + return findPackagesFromNonFile(baseUri, loader: http.readBytes); } else { return new Future.value(Packages.noPackages); } @@ -140,8 +191,8 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// of the requested `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) { - if (loader == null) loader = _httpGet; + {Future> loader(Uri name)}) { + if (loader == null) loader = http.readBytes; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List fileBytes) { Map map = pkgfile.parse(fileBytes, packagesFileUri); @@ -152,30 +203,3 @@ Future findPackagesFromNonFile(Uri nonFileUri, return new NonFilePackagesDirectoryPackages(packagesDirectoryUri); }); } - -/// Fetches a file over http. -Future> _httpGet(Uri uri) { - HttpClient client = new HttpClient(); - return client - .getUrl(uri) - .then((HttpClientRequest request) => request.close()) - .then((HttpClientResponse response) { - if (response.statusCode != HttpStatus.OK) { - String msg = 'Failure getting $uri: ' - '${response.statusCode} ${response.reasonPhrase}'; - throw msg; - } - return response.toList(); - }).then((List> splitContent) { - int totalLength = splitContent.fold(0, (int old, List list) { - return old + list.length; - }); - Uint8List result = new Uint8List(totalLength); - int offset = 0; - for (List contentPart in splitContent) { - result.setRange(offset, offset + contentPart.length, contentPart); - offset += contentPart.length; - } - return result; - }); -} diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 16544e43d..d89cc2fa9 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -205,6 +205,52 @@ main() { loader:loader); validatePackagesDir(resolver, location); }); + + generalTest("loadPackagesFile", + {".packages": packagesFile}, + (Uri directory) async { + Uri file = directory.resolve(".packages"); + Packages resolver = await loadPackagesFile(file); + validatePackagesFile(resolver, file); + }); + + generalTest("loadPackagesFile non-default name", + {"pheldagriff": packagesFile}, + (Uri directory) async { + Uri file = directory.resolve("pheldagriff"); + Packages resolver = await loadPackagesFile(file); + validatePackagesFile(resolver, file); + }); + + test("loadPackagesFile w/ loader", () async { + loader(Uri uri) async => packagesFile.codeUnits; + Uri file = Uri.parse("krutz://example.com/.packages"); + Packages resolver = await loadPackagesFile(file, loader: loader); + validatePackagesFile(resolver, file); + }); + + generalTest("loadPackagesFile not found", + {}, + (Uri directory) async { + Uri file = directory.resolve(".packages"); + expect(loadPackagesFile(file), throws); + }); + + generalTest("loadPackagesFile syntax error", + {".packages": "syntax error"}, + (Uri directory) async { + Uri file = directory.resolve(".packages"); + expect(loadPackagesFile(file), throws); + }); + + generalTest("getPackagesDir", + {"packages": {"foo": {}, "bar": {}, "baz": {}}}, + (Uri directory) async { + Uri packages = directory.resolve("packages/"); + Packages resolver = getPackagesDirectory(packages); + Uri resolved = resolver.resolve(pkg("foo","flip/flop")); + expect(resolved, packages.resolve("foo/flip/flop")); + }); } /// Create a directory structure from [description] and run [fileTest]. @@ -285,5 +331,3 @@ void _createFiles(Directory target, Map description) { } }); } - - From 4eace8962445c84f69383010495a3a7b33ff37bd Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 10 Jun 2015 14:03:44 +0200 Subject: [PATCH 039/281] Tweak comments added by `write` function on packages_file.dart. Now adds "# " in front, not just "#", and doesn't treat the empty string after a final "\n" as an extra line. R=sgjesse@google.com Review URL: https://codereview.chromium.org//1167223004. --- pkgs/package_config/lib/packages_file.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 2228cb3f0..a736ca0b5 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -74,7 +74,9 @@ Map parse(List source, Uri baseLocation) { /// Writes the mapping to a [StringSink]. /// /// If [comment] is provided, the output will contain this comment -/// with `#` in front of each line. +/// with `# ` in front of each line. +/// Lines are defined as ending in line feed (`'\n'`). If the final +/// line of the comment doesn't end in a line feed, one will be added. /// /// If [baseUri] is provided, package locations will be made relative /// to the base URI, if possible, before writing. @@ -85,8 +87,10 @@ void write(StringSink output, Map packageMapping, } if (comment != null) { - for (var commentLine in comment.split('\n')) { - output.write('#'); + var lines = comment.split('\n'); + if (lines.last.isEmpty) lines.removeLast(); + for (var commentLine in lines) { + output.write('# '); output.writeln(commentLine); } } else { @@ -172,4 +176,4 @@ Uri _relativize(Uri uri, Uri baseUri) { } // TODO: inline to uri.normalizePath() when we move to 1.11 -Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); +Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); From 3f171c5fee0b34fa64af46d4ab473c06821a314f Mon Sep 17 00:00:00 2001 From: Sigmund Cherem Date: Tue, 16 Jun 2015 09:42:56 -0700 Subject: [PATCH 040/281] Make tests pass R=het@google.com, lrn@google.com Review URL: https://codereview.chromium.org//1178673002. --- pkgs/package_config/lib/discovery.dart | 29 +++++++++++++++++-- pkgs/package_config/pubspec.yaml | 4 +-- .../test/discovery_analysis_test.dart | 12 ++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 35c3ece7f..a399395cb 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -38,7 +38,7 @@ Future loadPackagesFile(Uri packagesFile, return file.readAsBytes().then(parseBytes); } if (loader == null) { - return http.readBytes(packagesFile).then(parseBytes); + return _httpGet(packagesFile).then(parseBytes); } return loader(packagesFile).then(parseBytes); } @@ -99,7 +99,7 @@ Future findPackages(Uri baseUri, } else if (loader != null) { return findPackagesFromNonFile(baseUri, loader: loader); } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, loader: http.readBytes); + return findPackagesFromNonFile(baseUri, loader: _httpGet); } else { return new Future.value(Packages.noPackages); } @@ -192,7 +192,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, {Future> loader(Uri name)}) { - if (loader == null) loader = http.readBytes; + if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List fileBytes) { Map map = pkgfile.parse(fileBytes, packagesFileUri); @@ -203,3 +203,26 @@ Future findPackagesFromNonFile(Uri nonFileUri, return new NonFilePackagesDirectoryPackages(packagesDirectoryUri); }); } + +/// Fetches a file over http. +Future> _httpGet(Uri uri) async { + HttpClient client = new HttpClient(); + HttpClientRequest request = await client.getUrl(uri); + HttpClientResponse response = await request.close(); + if (response.statusCode != HttpStatus.OK) { + throw 'Failure getting $uri: ' + '${response.statusCode} ${response.reasonPhrase}'; + } + List> splitContent = await response.toList(); + int totalLength = 0; + for (var list in splitContent) { + totalLength += list.length; + } + Uint8List result = new Uint8List(totalLength); + int offset = 0; + for (List contentPart in splitContent) { + result.setRange(offset, offset + contentPart.length, contentPart); + offset += contentPart.length; + } + return result; +} diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 0f2735b53..0b780d9d7 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -8,8 +8,8 @@ environment: sdk: '>=1.11.0-dev.0.0 <2.0.0' dependencies: - charcode: '^1.1.0' - path: '>=1.0.0 <2.0.0' + charcode: ^1.1.0 + path: ^1.0.0 dev_dependencies: test: '>=0.12.0 <0.13.0' diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart index ad007c073..38599f895 100644 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -19,19 +19,19 @@ main() { (Directory directory) { var dirUri = new Uri.directory(directory.path); PackageContext ctx = PackageContext.findAll(directory); - PackagesContext root = ctx[directory]; + PackageContext root = ctx[directory]; expect(root, same(ctx)); validatePackagesFile(root.packages, dirUri); var fooDir = sub(directory, "foo"); - PackagesContext foo = ctx[fooDir]; + PackageContext foo = ctx[fooDir]; expect(identical(root, foo), isFalse); validatePackagesFile(foo.packages, dirUri.resolve("foo/")); var barDir = sub(directory, "bar"); - PackagesContext bar = ctx[sub(directory, "bar")]; + PackageContext bar = ctx[sub(directory, "bar")]; validatePackagesDir(bar.packages, dirUri.resolve("bar/")); - PackagesContext barbar = ctx[sub(barDir, "bar")]; + PackageContext barbar = ctx[sub(barDir, "bar")]; expect(barbar, same(bar)); // inherited. - PackagesContext baz = ctx[sub(directory, "baz")]; + PackageContext baz = ctx[sub(directory, "baz")]; expect(baz, same(root)); // inherited. var map = ctx.asMap(); @@ -95,7 +95,7 @@ Uri pkg(String packageName, String packagePath) { /// as a string. void fileTest(String name, Map description, - Future fileTest(Uri directory)) { + Future fileTest(Directory directory)) { group("file-test", () { Directory tempDir = Directory.systemTemp.createTempSync("file-test"); setUp(() { From ca0681f4325686bf9350e5a80e289b71f44f1b88 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 24 Jun 2015 08:00:52 +0200 Subject: [PATCH 041/281] Update to new syntax. R=het@google.com, pquitslund@google.com Review URL: https://codereview.chromium.org//1178213004. --- .../lib/discovery_analysis.dart | 1 - pkgs/package_config/lib/packages_file.dart | 30 ++++--- pkgs/package_config/lib/src/util.dart | 66 ++++++++++----- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/all.dart | 10 ++- .../test/discovery_analysis_test.dart | 8 +- pkgs/package_config/test/discovery_test.dart | 8 +- pkgs/package_config/test/parse_test.dart | 64 +++++++------- .../package_config/test/parse_write_test.dart | 84 +++++++++++++++++++ 9 files changed, 200 insertions(+), 73 deletions(-) create mode 100644 pkgs/package_config/test/parse_write_test.dart diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index f3bcac68e..af4df070a 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -18,7 +18,6 @@ import "dart:collection" show HashMap; import "package:path/path.dart" as path; import "packages.dart"; -import "discovery.dart"; import "packages_file.dart" as pkgfile; import "src/packages_impl.dart"; import "src/packages_io_impl.dart"; diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index a736ca0b5..73e6061c9 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -5,7 +5,7 @@ library package_config.packages_file; import "package:charcode/ascii.dart"; -import "src/util.dart" show isIdentifier; +import "src/util.dart" show isValidPackageName; /// Parses a `.packages` file into a map from package name to base URI. /// @@ -28,34 +28,34 @@ Map parse(List source, Uri baseLocation) { while (index < source.length) { bool isComment = false; int start = index; - int eqIndex = -1; + int separatorIndex = -1; int end = source.length; int char = source[index++]; if (char == $cr || char == $lf) { continue; } - if (char == $equal) { + if (char == $colon) { throw new FormatException("Missing package name", source, index - 1); } isComment = char == $hash; while (index < source.length) { char = source[index++]; - if (char == $equal && eqIndex < 0) { - eqIndex = index - 1; + if (char == $colon && separatorIndex < 0) { + separatorIndex = index - 1; } else if (char == $cr || char == $lf) { end = index - 1; break; } } if (isComment) continue; - if (eqIndex < 0) { - throw new FormatException("No '=' on line", source, index - 1); + if (separatorIndex < 0) { + throw new FormatException("No ':' on line", source, index - 1); } - var packageName = new String.fromCharCodes(source, start, eqIndex); - if (!isIdentifier(packageName)) { + var packageName = new String.fromCharCodes(source, start, separatorIndex); + if (!isValidPackageName(packageName)) { throw new FormatException("Not a valid package name", packageName, 0); } - var packageUri = new String.fromCharCodes(source, eqIndex + 1, end); + var packageUri = new String.fromCharCodes(source, separatorIndex + 1, end); var packageLocation = Uri.parse(packageUri); if (!packageLocation.path.endsWith('/')) { packageLocation = @@ -101,11 +101,11 @@ void write(StringSink output, Map packageMapping, packageMapping.forEach((String packageName, Uri uri) { // Validate packageName. - if (!isIdentifier(packageName)) { + if (!isValidPackageName(packageName)) { throw new ArgumentError('"$packageName" is not a valid package name'); } output.write(packageName); - output.write('='); + output.write(':'); // If baseUri provided, make uri relative. if (baseUri != null) { uri = _relativize(uri, baseUri); @@ -124,7 +124,7 @@ void write(StringSink output, Map packageMapping, /// but may be relative. /// The `baseUri` must be absolute. Uri _relativize(Uri uri, Uri baseUri) { - assert(!baseUri.isAbsolute); + assert(baseUri.isAbsolute); if (uri.hasQuery || uri.hasFragment) { uri = new Uri( scheme: uri.scheme, @@ -158,6 +158,7 @@ Uri _relativize(Uri uri, Uri baseUri) { } uri = _normalizePath(uri); List target = uri.pathSegments.toList(); + if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); int index = 0; while (index < base.length && index < target.length) { if (base[index] != target[index]) { @@ -166,6 +167,9 @@ Uri _relativize(Uri uri, Uri baseUri) { index++; } if (index == base.length) { + if (index == target.length) { + return new Uri(path: "./"); + } return new Uri(path: target.skip(index).join('/')); } else if (index > 0) { return new Uri( diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index abf1d52f0..badf64086 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -7,27 +7,39 @@ library package_config.util; import "package:charcode/ascii.dart"; -/// Tests whether something is a valid Dart identifier/package name. -bool isIdentifier(String string) { - if (string.isEmpty) return false; - int firstChar = string.codeUnitAt(0); - int firstCharLower = firstChar | 0x20; - if (firstCharLower < $a || firstCharLower > $z) { - if (firstChar != $_ && firstChar != $$) return false; - } - for (int i = 1; i < string.length; i++) { - int char = string.codeUnitAt(i); - int charLower = char | 0x20; - if (charLower < $a || charLower > $z) { // Letters. - if ((char ^ 0x30) <= 9) continue; // Digits. - if (char == $_ || char == $$) continue; // $ and _ - if (firstChar != $_ && firstChar != $$) return false; +// All ASCII characters that are valid in a package name, with space +// for all the invalid ones (including space). +const String _validPackageNameCharacters = + r" ! $ &'()*+,-. 0123456789 ; = " + r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ~ "; + +/// Tests whether something is a valid Dart package name. +bool isValidPackageName(String string) { + return _findInvalidCharacter(string) < 0; +} + +/// Check if a string is a valid package name. +/// +/// Valid package names contain only characters in [_validPackageNameCharacters] +/// and must contain at least one non-'.' character. +/// +/// Returns `-1` if the string is valid. +/// Otherwise returns the index of the first invalid character, +/// or `string.length` if the string contains no non-'.' character. +int _findInvalidCharacter(String string) { + // Becomes non-zero if any non-'.' character is encountered. + int nonDot = 0; + for (int i = 0; i < string.length; i++) { + var c = string.codeUnitAt(i); + if (c > 0x7f || _validPackageNameCharacters.codeUnitAt(c) <= $space) { + return i; } + nonDot += c ^ $dot; } - return true; + if (nonDot == 0) return string.length; + return -1; } - /// Validate that a Uri is a valid package:URI. String checkValidPackageUri(Uri packageUri) { if (packageUri.scheme != "package") { @@ -61,9 +73,25 @@ String checkValidPackageUri(Uri packageUri) { "Package URIs must start with the package name followed by a '/'"); } String packageName = packageUri.path.substring(0, firstSlash); - if (!isIdentifier(packageName)) { + int badIndex = _findInvalidCharacter(packageName); + if (badIndex >= 0) { + if (packageName.isEmpty) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package names mus be non-empty"); + } + if (badIndex == packageName.length) { + throw new ArgumentError.value(packageUri, "packageUri", + "Package names must contain at least one non-'.' character"); + } + assert(badIndex < packageName.length); + int badCharCode = packageName.codeUnitAt(badIndex); + var badChar = "U+" + badCharCode.toRadixString(16).padLeft(4, '0'); + if (badCharCode >= 0x20 && badCharCode <= 0x7e) { + // Printable character. + badChar = "'${packageName[badIndex]}' ($badChar)"; + } throw new ArgumentError.value(packageUri, "packageUri", - "Package names must be valid identifiers"); + "Package names must not contain $badChar"); } return packageName; } diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 0b780d9d7..2d96c9035 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.0.4 +version: 0.1.0 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart index 79f5b3574..78e6cffd1 100644 --- a/pkgs/package_config/test/all.dart +++ b/pkgs/package_config/test/all.dart @@ -2,10 +2,16 @@ // 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. +import "package:test/test.dart"; + +import "discovery_analysis_test.dart" as discovery_analysis; import "discovery_test.dart" as discovery; import "parse_test.dart" as parse; +import "parse_write_test.dart" as parse_write; main() { - parse.main(); - discovery.main(); + group("parse:", parse.main); + group("discovery:", discovery.main); + group("discovery-analysis:", discovery_analysis.main); + group("parse/write:", parse_write.main); } diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart index 38599f895..f33a4a8c6 100644 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -2,6 +2,8 @@ // 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 package_config.discovery_analysis_test; + import "dart:async"; import "dart:io"; @@ -46,9 +48,9 @@ Directory sub(Directory parent, String dirName) { const packagesFile = """ # A comment -foo=file:///dart/packages/foo/ -bar=http://example.com/dart/packages/bar/ -baz=packages/baz/ +foo:file:///dart/packages/foo/ +bar:http://example.com/dart/packages/bar/ +baz:packages/baz/ """; void validatePackagesFile(Packages resolver, Uri location) { diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index d89cc2fa9..4f780c2ad 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -2,6 +2,8 @@ // 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 package_config.discovery_test; + import "dart:async"; import "dart:io"; import "package:test/test.dart"; @@ -11,9 +13,9 @@ import "package:path/path.dart" as path; const packagesFile = """ # A comment -foo=file:///dart/packages/foo/ -bar=http://example.com/dart/packages/bar/ -baz=packages/baz/ +foo:file:///dart/packages/foo/ +bar:http://example.com/dart/packages/bar/ +baz:packages/baz/ """; void validatePackagesFile(Packages resolver, Uri location) { diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index ddd8ff6ca..902d8cea8 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -2,7 +2,7 @@ // 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 test_all; +library package_config.parse_test; import "package:package_config/packages.dart"; import "package:package_config/packages_file.dart" show parse; @@ -81,27 +81,27 @@ main() { equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - test("all valid chars", () { + test("all valid chars can be used in URI segment", () { var packages = doParse(allValidCharsSample, base); expect(packages.packages.toList(), equals([allValidChars])); expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - test("no escapes", () { - expect(() => doParse("x%41x=x", base), throws); + test("no invalid chars accepted", () { + var map = {}; + for (int i = 0; i < allValidChars.length; i++) { + map[allValidChars.codeUnitAt(i)] = true; + } + for (int i = 0; i <= 255; i++) { + if (map[i] == true) continue; + var char = new String.fromCharCode(i); + expect(() => doParse("x${char}x:x"), throws); + } }); - test("not identifiers", () { - expect(() => doParse("1x=x", base), throws); - expect(() => doParse(" x=x", base), throws); - expect(() => doParse("\\x41x=x", base), throws); - expect(() => doParse("x@x=x", base), throws); - expect(() => doParse("x[x=x", base), throws); - expect(() => doParse("x`x=x", base), throws); - expect(() => doParse("x{x=x", base), throws); - expect(() => doParse("x/x=x", base), throws); - expect(() => doParse("x:x=x", base), throws); + test("no escapes", () { + expect(() => doParse("x%41x:x", base), throws); }); test("same name twice", () { @@ -131,26 +131,28 @@ Packages doParse(String sample, Uri baseUri) { var emptySample = ""; var commentOnlySample = "# comment only\n"; var emptyLinesSample = "\n\n\r\n"; -var singleRelativeSample = "foo=../test/\n"; -var singleRelativeSampleNoSlash = "foo=../test\n"; -var singleRelativeSampleNoNewline = "foo=../test/"; -var singleAbsoluteSample = "foo=http://example.com/some/where/\n"; -var multiRelativeSample = "foo=../test/\nbar=../test2/\n"; +var singleRelativeSample = "foo:../test/\n"; +var singleRelativeSampleNoSlash = "foo:../test\n"; +var singleRelativeSampleNoNewline = "foo:../test/"; +var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; +var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; // All valid path segment characters in an URI. var allValidChars = - r"$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; -var allValidCharsSample = "${allValidChars.replaceAll('=', '%3D')}=../test/\n"; -var allUnreservedChars = - "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; + r"!$&'()*+,-.0123456789;=" + r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; + +var allValidCharsSample = "${allValidChars}:../test/\n"; // Invalid samples. var invalid = [ - "foobar:baz.dart", // no equals - ".=../test/", // dot segment - "..=../test/", // dot-dot segment - "foo/bar=../test/", // - "/foo=../test/", // var multiSegmentSample - "?=../test/", // invalid characters in path segment. - "[=../test/", // invalid characters in path segment. - "x#=../test/", // invalid characters in path segment. + ":baz.dart", // empty. + "foobar=baz.dart", // no colon (but an equals, which is not the same) + ".:../test/", // dot segment + "..:../test/", // dot-dot segment + "...:../test/", // dot-dot-dot segment + "foo/bar:../test/", // slash in name + "/foo:../test/", // slash at start of name + "?:../test/", // invalid characters. + "[:../test/", // invalid characters. + "x#:../test/", // invalid characters. ]; diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart new file mode 100644 index 000000000..fde9616ea --- /dev/null +++ b/pkgs/package_config/test/parse_write_test.dart @@ -0,0 +1,84 @@ +// Copyright (c) 2015, 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 package_config.parse_write_test; + +import "package:package_config/packages.dart"; +import "package:package_config/packages_file.dart"; +import "package:test/test.dart"; + +main() { + testBase(baseDirString) { + var baseDir = Uri.parse(baseDirString); + group("${baseDir.scheme} base", () { + Uri packagesFile = baseDir.resolve(".packages"); + + roundTripTest(String name, Map map) { + group(name, () { + test("write with no baseUri", () { + var content = writeToString(map).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + + test("write with base directory", () { + var content = writeToString(map, baseUri: baseDir).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + + test("write with base .packages file", () { + var content = writeToString(map, baseUri: packagesFile).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + }); + } + var lowerDir = baseDir.resolve("path3/path4/"); + var higherDir = baseDir.resolve("../"); + var parallelDir = baseDir.resolve("../path3/"); + var rootDir = baseDir.resolve("/"); + var fileDir = Uri.parse("file:///path1/part2/"); + var httpDir = Uri.parse("http://example.com/path1/path2/"); + var otherDir = Uri.parse("other:/path1/path2/"); + + roundTripTest("empty", {}); + roundTripTest("lower directory", {"foo": lowerDir}); + roundTripTest("higher directory", {"foo": higherDir}); + roundTripTest("parallel directory", {"foo": parallelDir}); + roundTripTest("same directory", {"foo": baseDir}); + roundTripTest("root directory", {"foo": rootDir}); + roundTripTest("file directory", {"foo": fileDir}); + roundTripTest("http directory", {"foo": httpDir}); + roundTripTest("other scheme directory", {"foo": otherDir}); + roundTripTest("multiple same-type directories", + {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); + roundTripTest("multiple scheme directories", + {"foo": fileDir, "bar": httpDir, "baz": otherDir}); + roundTripTest("multiple scheme directories and mutliple same type", + {"foo": fileDir, "bar": httpDir, "baz": otherDir, + "qux": lowerDir, "hip": higherDir, "dep": parallelDir}); + }); + } + + testBase("file:///base1/base2/"); + testBase("http://example.com/base1/base2/"); + testBase("other:/base1/base2/"); + + // Check that writing adds the comment. + test("write preserves comment", () { + var comment = "comment line 1\ncomment line 2\ncomment line 3"; + var result = writeToString({}, comment: comment); + // Comment with "# " before each line and "\n" after last. + var expectedComment = + "# comment line 1\n# comment line 2\n# comment line 3\n"; + expect(result, startsWith(expectedComment)); + }); +} + +String writeToString(Map map, {Uri baseUri, String comment}) { + var buffer = new StringBuffer(); + write(buffer, map, baseUri: baseUri, comment: comment); + return buffer.toString(); +} From 3b11c03435f18fab1943e94ff3d680a098a0d961 Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 24 Jun 2015 09:06:02 -0700 Subject: [PATCH 042/281] Build fixes [TBR]. --- pkgs/package_config/test/parse_test.dart | 2 +- pkgs/package_config/test/parse_write_test.dart | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 902d8cea8..3c02c84b6 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -96,7 +96,7 @@ main() { for (int i = 0; i <= 255; i++) { if (map[i] == true) continue; var char = new String.fromCharCode(i); - expect(() => doParse("x${char}x:x"), throws); + expect(() => doParse("x${char}x:x", null), throws); } }); diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart index fde9616ea..6a185db20 100644 --- a/pkgs/package_config/test/parse_write_test.dart +++ b/pkgs/package_config/test/parse_write_test.dart @@ -4,7 +4,6 @@ library package_config.parse_write_test; -import "package:package_config/packages.dart"; import "package:package_config/packages_file.dart"; import "package:test/test.dart"; From 8110c7a4a8e0119a0625d5e2caa3110a9e236de5 Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 24 Jun 2015 09:13:40 -0700 Subject: [PATCH 043/281] Version bump. --- pkgs/package_config/CHANGELOG.md | 11 +++++++++-- pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 2a2d63cf8..625f48625 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog -## 0.0.1 +## 0.1.1 + +- Syntax updates. + + +## 0.1.0 + +- Initial implementation. + -- Initial version diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 2d96c9035..72406801e 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.0 +version: 0.1.1 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 150f467e4697f39cf4b52bf4cb34e305f65696ad Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 24 Jun 2015 15:04:34 -0700 Subject: [PATCH 044/281] Add Pool.allowRelease(). This allows a resource to indicate that it can be released without forcing it to deallocate immediately. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1205133002. --- pkgs/pool/CHANGELOG.md | 5 ++ pkgs/pool/lib/pool.dart | 76 +++++++++++++++++++++-- pkgs/pool/pubspec.yaml | 4 +- pkgs/pool/test/pool_test.dart | 113 ++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 7 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 4fa87caec..ec8fd79a8 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0 + +* Add `PoolResource.allowRelease()`, which allows a resource to indicate that it + can be released without forcing it to deallocate immediately. + ## 1.0.2 * Fixed the homepage. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 61482e3f2..6941229b3 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -24,6 +24,19 @@ class Pool { /// be completed. final _requestedResources = new Queue>(); + /// Callbacks that must be called before additional resources can be + /// allocated. + /// + /// See [PoolResource.allowRelease]. + final _onReleaseCallbacks = new Queue(); + + /// Completers that will be completed once `onRelease` callbacks are done + /// running. + /// + /// These are kept in a queue to ensure that the earliest request completes + /// first regardless of what order the `onRelease` callbacks complete in. + final _onReleaseCompleters = new Queue>(); + /// The maximum number of resources that may be allocated at once. final int _maxAllocatedResources; @@ -59,6 +72,8 @@ class Pool { if (_allocatedResources < _maxAllocatedResources) { _allocatedResources++; return new Future.value(new PoolResource._(this)); + } else if (_onReleaseCallbacks.isNotEmpty) { + return _runOnRelease(_onReleaseCallbacks.removeFirst()); } else { var completer = new Completer(); _requestedResources.add(completer); @@ -78,24 +93,53 @@ class Pool { /// If there are any pending requests, this will fire the oldest one. void _onResourceReleased() { + _resetTimer(); + if (_requestedResources.isEmpty) { _allocatedResources--; - if (_timer != null) { - _timer.cancel(); - _timer = null; - } return; } - _resetTimer(); var pending = _requestedResources.removeFirst(); pending.complete(new PoolResource._(this)); } + /// If there are any pending requests, this will fire the oldest one after + /// running [onRelease]. + void _onResourceReleaseAllowed(onRelease()) { + _resetTimer(); + + if (_requestedResources.isEmpty) { + _onReleaseCallbacks.add( + Zone.current.bindCallback(onRelease, runGuarded: false)); + return; + } + + var pending = _requestedResources.removeFirst(); + pending.complete(_runOnRelease(onRelease)); + } + + /// Runs [onRelease] and returns a Future that completes to a resource once an + /// [onRelease] callback completes. + /// + /// Futures returned by [_runOnRelease] always complete in the order they were + /// created, even if earlier [onRelease] callbacks take longer to run. + Future _runOnRelease(onRelease()) { + new Future.sync(onRelease).then((value) { + _onReleaseCompleters.removeFirst().complete(new PoolResource._(this)); + }).catchError((error, stackTrace) { + _onReleaseCompleters.removeFirst().completeError(error, stackTrace); + }); + + var completer = new Completer.sync(); + _onReleaseCompleters.add(completer); + return completer.future; + } + /// A resource has been requested, allocated, or released. void _resetTimer() { if (_timer != null) _timer.cancel(); - if (_timeout == null) { + if (_timeout == null || _requestedResources.isEmpty) { _timer = null; } else { _timer = new Timer(_timeout, _onTimeout); @@ -138,5 +182,25 @@ class PoolResource { _released = true; _pool._onResourceReleased(); } + + /// Tells the parent [Pool] that the resource associated with this resource is + /// no longer necessary, but should remain allocated until more resources are + /// needed. + /// + /// When [Pool.request] is called and there are no remaining available + /// resources, the [onRelease] callback is called. It should free the + /// resource, and it may return a Future or `null`. Once that completes, the + /// [Pool.request] call will complete to a new [PoolResource]. + /// + /// This is useful when a resource's main function is complete, but it may + /// produce additional information later on. For example, an isolate's task + /// may be complete, but it could still emit asynchronous errors. + void allowRelease(onRelease()) { + if (_released) { + throw new StateError("A PoolResource may only be released once."); + } + _released = true; + _pool._onResourceReleaseAllowed(onRelease); + } } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 19aac1e54..175c8dc74 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,12 @@ name: pool -version: 1.0.2 +version: 1.1.0 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool dependencies: stack_trace: ">=0.9.2 <2.0.0" +environment: + sdk: ">=1.9.0 <2.0.0" dev_dependencies: fake_async: ">=0.1.0 <0.2.0" test: ">=0.12.0 <0.13.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index b654801e1..64bc3a6cc 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -159,6 +159,119 @@ void main() { }); }); }); + + group("allowRelease()", () { + test("runs the callback once the resource limit is exceeded", () async { + var pool = new Pool(50); + var requests = []; + for (var i = 0; i < 49; i++) { + expect(pool.request(), completes); + } + + var resource = await pool.request(); + var onReleaseCalled = false; + resource.allowRelease(() => onReleaseCalled = true); + await new Future.delayed(Duration.ZERO); + expect(onReleaseCalled, isFalse); + + expect(pool.request(), completes); + await new Future.delayed(Duration.ZERO); + expect(onReleaseCalled, isTrue); + }); + + test("runs the callback immediately if there are blocked requests", + () async { + var pool = new Pool(1); + var resource = await pool.request(); + + // This will be blocked until [resource.allowRelease] is called. + expect(pool.request(), completes); + + var onReleaseCalled = false; + resource.allowRelease(() => onReleaseCalled = true); + await new Future.delayed(Duration.ZERO); + expect(onReleaseCalled, isTrue); + }); + + test("blocks the request until the callback completes", () async { + var pool = new Pool(1); + var resource = await pool.request(); + + var requestComplete = false; + pool.request().then((_) => requestComplete = true); + + var completer = new Completer(); + resource.allowRelease(() => completer.future); + await new Future.delayed(Duration.ZERO); + expect(requestComplete, isFalse); + + completer.complete(); + await new Future.delayed(Duration.ZERO); + expect(requestComplete, isTrue); + }); + + test("completes requests in request order regardless of callback order", + () async { + var pool = new Pool(2); + var resource1 = await pool.request(); + var resource2 = await pool.request(); + + var request1Complete = false; + pool.request().then((_) => request1Complete = true); + var request2Complete = false; + pool.request().then((_) => request2Complete = true); + + var onRelease1Called = false; + var completer1 = new Completer(); + resource1.allowRelease(() { + onRelease1Called = true; + return completer1.future; + }); + await new Future.delayed(Duration.ZERO); + expect(onRelease1Called, isTrue); + + var onRelease2Called = false; + var completer2 = new Completer(); + resource2.allowRelease(() { + onRelease2Called = true; + return completer2.future; + }); + await new Future.delayed(Duration.ZERO); + expect(onRelease2Called, isTrue); + expect(request1Complete, isFalse); + expect(request2Complete, isFalse); + + // Complete the second resource's onRelease callback first. Even though it + // was triggered by the second blocking request, it should complete the + // first one to preserve ordering. + completer2.complete(); + await new Future.delayed(Duration.ZERO); + expect(request1Complete, isTrue); + expect(request2Complete, isFalse); + + completer1.complete(); + await new Future.delayed(Duration.ZERO); + expect(request1Complete, isTrue); + expect(request2Complete, isTrue); + }); + + test("runs onRequest in the zone it was created", () async { + var pool = new Pool(1); + var resource = await pool.request(); + + var outerZone = Zone.current; + runZoned(() { + var innerZone = Zone.current; + expect(innerZone, isNot(equals(outerZone))); + + resource.allowRelease(expectAsync(() { + expect(Zone.current, equals(innerZone)); + })); + }); + + pool.request(); + }); + }); } /// Returns a function that will cause the test to fail if it's called. From 05a0a88ca11541d9c51498666ba5d5893e97a94a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 30 Jun 2015 17:46:36 -0700 Subject: [PATCH 045/281] remove usage of Chain.track The min SDK is already 1.9, so we're not leaving anyone behind Also removed an unused variable in pool_test R=nweiz@google.com Review URL: https://codereview.chromium.org//1215053004. --- pkgs/pool/lib/pool.dart | 3 +-- pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 6941229b3..e8ee99cab 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -87,8 +87,7 @@ class Pool { /// /// The return value of [callback] is piped to the returned Future. Future withResource(callback()) { - return request().then((resource) => - Chain.track(new Future.sync(callback)).whenComplete(resource.release)); + return request().then((resource) => new Future.sync(callback).whenComplete(resource.release)); } /// If there are any pending requests, this will fire the oldest one. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 175c8dc74..cc2d367be 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.1.0 +version: 1.1.1-dev author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 64bc3a6cc..5dfef2a24 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -163,7 +163,6 @@ void main() { group("allowRelease()", () { test("runs the callback once the resource limit is exceeded", () async { var pool = new Pool(50); - var requests = []; for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } From 3351876c810771f337a05cf2950dce94ce594cde Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 13 Jul 2015 09:19:24 +0200 Subject: [PATCH 046/281] Don't allow package:-URIs as package locations when creating .packages file. R=pquitslund@google.com Review URL: https://codereview.chromium.org//1227283002 . --- pkgs/package_config/lib/discovery.dart | 2 +- pkgs/package_config/lib/packages_file.dart | 7 +++++++ pkgs/package_config/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index a399395cb..8e42af79d 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -179,7 +179,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// script. /// The [nonFileUri] should not be a `file:` URI since the algorithm for /// finding a package resolution strategy is more elaborate for `file:` URIs. -/// In that case, use [findPackagesFile]. +/// In that case, use [findPackagesFromFile]. /// /// This function first tries to locate a `.packages` file in the [nonFileUri] /// directory. If that is not found, it instead assumes a `packages/` directory diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 73e6061c9..25d2d6883 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -80,6 +80,9 @@ Map parse(List source, Uri baseLocation) { /// /// If [baseUri] is provided, package locations will be made relative /// to the base URI, if possible, before writing. +/// +/// All the keys of [packageMapping] must be valid package names, +/// and the values must be URIs that do not have the `package:` scheme. void write(StringSink output, Map packageMapping, {Uri baseUri, String comment}) { if (baseUri != null && !baseUri.isAbsolute) { @@ -104,6 +107,10 @@ void write(StringSink output, Map packageMapping, if (!isValidPackageName(packageName)) { throw new ArgumentError('"$packageName" is not a valid package name'); } + if (uri.scheme == "package") { + throw new ArgumentError.value( + "Package location must not be a package: URI", uri); + } output.write(packageName); output.write(':'); // If baseUri provided, make uri relative. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 72406801e..d3acb9064 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.1 +version: 0.1.2 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 188ef5d26cea22fef00a6bcbef38cea16df5a092 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Jul 2015 13:29:56 -0700 Subject: [PATCH 047/281] Use the new test runner on the bots. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1235143003 . --- pkgs/pool/.gitignore | 1 + pkgs/pool/.status | 15 --------------- pkgs/pool/.test_config | 3 +++ 3 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 pkgs/pool/.status create mode 100644 pkgs/pool/.test_config diff --git a/pkgs/pool/.gitignore b/pkgs/pool/.gitignore index 388eff0ba..7dbf0350d 100644 --- a/pkgs/pool/.gitignore +++ b/pkgs/pool/.gitignore @@ -3,6 +3,7 @@ .pub/ build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/pool/.status b/pkgs/pool/.status deleted file mode 100644 index ff095a2f7..000000000 --- a/pkgs/pool/.status +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2014, 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. - -# Skip non-test files ending with "_test". -packages/*: Skip -*/packages/*: Skip -*/*/packages/*: Skip -*/*/*/packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip - -# Only run tests from the build directory, since we don't care about the -# difference between transformed an untransformed code. -test/*: Skip diff --git a/pkgs/pool/.test_config b/pkgs/pool/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/pool/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file From 5bd94be91cae69f085ee77f0143262b01500f081 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 14 Aug 2015 16:47:02 -0700 Subject: [PATCH 048/281] remove checked-in pubspec.lock and ignore .packages --- pkgs/package_config/.gitignore | 3 +- pkgs/package_config/pubspec.lock | 87 -------------------------------- 2 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 pkgs/package_config/pubspec.lock diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index f48e3c9a8..b46f3df8e 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -4,4 +4,5 @@ packages build .project .settings -pubspec.lock \ No newline at end of file +pubspec.lock +.packages diff --git a/pkgs/package_config/pubspec.lock b/pkgs/package_config/pubspec.lock deleted file mode 100644 index 5cae00509..000000000 --- a/pkgs/package_config/pubspec.lock +++ /dev/null @@ -1,87 +0,0 @@ -# Generated by pub -# See http://pub.dartlang.org/doc/glossary.html#lockfile -packages: - analyzer: - description: analyzer - source: hosted - version: "0.25.0+1" - args: - description: args - source: hosted - version: "0.13.0" - barback: - description: barback - source: hosted - version: "0.15.2+4" - charcode: - description: charcode - source: hosted - version: "1.1.0" - collection: - description: collection - source: hosted - version: "1.1.1" - crypto: - description: crypto - source: hosted - version: "0.9.0" - http_parser: - description: http_parser - source: hosted - version: "0.0.2+6" - matcher: - description: matcher - source: hosted - version: "0.12.0" - mime: - description: mime - source: hosted - version: "0.9.3" - path: - description: path - source: hosted - version: "1.3.5" - pool: - description: pool - source: hosted - version: "1.0.1" - pub_semver: - description: pub_semver - source: hosted - version: "1.2.0" - shelf: - description: shelf - source: hosted - version: "0.6.1+2" - shelf_static: - description: shelf_static - source: hosted - version: "0.2.2" - shelf_web_socket: - description: shelf_web_socket - source: hosted - version: "0.0.1+2" - source_span: - description: source_span - source: hosted - version: "1.1.2" - stack_trace: - description: stack_trace - source: hosted - version: "1.3.2" - string_scanner: - description: string_scanner - source: hosted - version: "0.1.3+1" - test: - description: test - source: hosted - version: "0.12.1" - watcher: - description: watcher - source: hosted - version: "0.9.5" - yaml: - description: yaml - source: hosted - version: "2.1.2" From 56cefdeb98f127f03e80bc29eb4caf5905f12fce Mon Sep 17 00:00:00 2001 From: pq Date: Tue, 18 Aug 2015 08:53:55 -0700 Subject: [PATCH 049/281] Invalid test cleanup (parse_test). --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/parse_test.dart | 7 ------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 625f48625..f4e355e2c 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.1.3-dev + +- Invalid test cleanup (to keepup with changes in `Uri`). + ## 0.1.1 - Syntax updates. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index d3acb9064..4cc000616 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.2 +version: 0.1.3-dev description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 3c02c84b6..6f830a103 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -74,13 +74,6 @@ main() { equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - test("dot-dot 2", () { - var packages = doParse(singleRelativeSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:qux/../foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - test("all valid chars can be used in URI segment", () { var packages = doParse(allValidCharsSample, base); expect(packages.packages.toList(), equals([allValidChars])); From c73974c3c5c918b9ccbde699e7c6ff81b8818e79 Mon Sep 17 00:00:00 2001 From: pq Date: Tue, 18 Aug 2015 09:45:31 -0700 Subject: [PATCH 050/281] Static warning fix. --- pkgs/package_config/lib/packages_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 25d2d6883..3f432aa70 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -109,7 +109,7 @@ void write(StringSink output, Map packageMapping, } if (uri.scheme == "package") { throw new ArgumentError.value( - "Package location must not be a package: URI", uri); + "Package location must not be a package: URI", uri.toString()); } output.write(packageName); output.write(':'); From 57e55d1ba4e85bb0f73b536d72174211f98d4f6a Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 20 Aug 2015 11:17:58 +0200 Subject: [PATCH 051/281] Add slash to package dir URI after resolving reference against base. Used to add slash to reference before resolving it. It only makes a difference for the empty URI reference which never makes sense anyway - this just ensures the error is the same as on the VM. It is, arguably, what the specification requires. R=sgjesse@google.com Review URL: https://codereview.chromium.org//1297923004. --- pkgs/package_config/lib/packages_file.dart | 2 +- pkgs/package_config/test/parse_test.dart | 32 ++++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 3f432aa70..f30781dc3 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -57,11 +57,11 @@ Map parse(List source, Uri baseLocation) { } var packageUri = new String.fromCharCodes(source, separatorIndex + 1, end); var packageLocation = Uri.parse(packageUri); + packageLocation = baseLocation.resolveUri(packageLocation); if (!packageLocation.path.endsWith('/')) { packageLocation = packageLocation.replace(path: packageLocation.path + "/"); } - packageLocation = baseLocation.resolveUri(packageLocation); if (result.containsKey(packageName)) { throw new FormatException( "Same package name occured twice.", source, start); diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 6f830a103..8ed5c2eb7 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -50,13 +50,27 @@ main() { equals(base.resolve("../test/").resolve("bar/baz.dart"))); }); - test("single absolute", () { + test("single absolute authority", () { var packages = doParse(singleAbsoluteSample, base); expect(packages.packages.toList(), equals(["foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); }); + test("single empty path", () { + var packages = doParse(singleEmptyPathSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.replace(path: "${base.path}/bar/baz.dart"))); + }); + + test("single absolute path", () { + var packages = doParse(singleAbsolutePathSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.replace(path: "/test/bar/baz.dart"))); + }); + test("multiple", () { var packages = doParse(multiRelativeSample, base); expect( @@ -121,14 +135,16 @@ Packages doParse(String sample, Uri baseUri) { } // Valid samples. -var emptySample = ""; -var commentOnlySample = "# comment only\n"; -var emptyLinesSample = "\n\n\r\n"; -var singleRelativeSample = "foo:../test/\n"; -var singleRelativeSampleNoSlash = "foo:../test\n"; +var emptySample = ""; +var commentOnlySample = "# comment only\n"; +var emptyLinesSample = "\n\n\r\n"; +var singleRelativeSample = "foo:../test/\n"; +var singleRelativeSampleNoSlash = "foo:../test\n"; var singleRelativeSampleNoNewline = "foo:../test/"; -var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; -var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; +var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; +var singleEmptyPathSample = "foo:\n"; +var singleAbsolutePathSample = "foo:/test/\n"; +var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; // All valid path segment characters in an URI. var allValidChars = r"!$&'()*+,-.0123456789;=" From 24e3e0c664fc0a667b825f722244956bdfb7a15c Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 20 Aug 2015 12:46:36 +0200 Subject: [PATCH 052/281] Update version number before publishing. BUG= Review URL: https://codereview.chromium.org/1301443005 . --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 4cc000616..f2c4e06cc 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.3-dev +version: 0.1.3 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From ba56d6613604908223abf6dd484daf66ac531f88 Mon Sep 17 00:00:00 2001 From: Seth Ladd Date: Wed, 16 Sep 2015 10:00:40 -0700 Subject: [PATCH 053/281] Go SSL --- pkgs/package_config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 9a0995d6b..0463719b3 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,7 +4,7 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](http://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) ## Features and bugs From f3bd1c5082a019d63d93432fdeec15a207327889 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 8 Oct 2015 17:46:26 -0700 Subject: [PATCH 054/281] Add Pool.close(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//1393193004 . --- pkgs/pool/CHANGELOG.md | 5 ++ pkgs/pool/lib/pool.dart | 76 ++++++++++++++++--- pkgs/pool/pubspec.yaml | 3 +- pkgs/pool/test/pool_test.dart | 133 ++++++++++++++++++++++++++++++++++ 4 files changed, 204 insertions(+), 13 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index ec8fd79a8..9f74d07b4 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.2.0 + +* Add `Pool.close()`, which forbids new resource requests and releases all + releasable resources. + ## 1.1.0 * Add `PoolResource.allowRelease()`, which allows a resource to indicate that it diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index e8ee99cab..59b949e0e 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -7,6 +7,7 @@ library pool; import 'dart:async'; import 'dart:collection'; +import 'package:async/async.dart'; import 'package:stack_trace/stack_trace.dart'; /// Manages an abstract pool of resources with a limit on how many may be in use @@ -55,6 +56,15 @@ class Pool { /// The amount of time to wait before timing out the pending resources. final Duration _timeout; + /// A [FutureGroup] that tracks all the `onRelease` callbacks for resources + /// that have been marked releasable. + /// + /// This is `null` until [close] is called. + FutureGroup _closeGroup; + + /// Whether [close] has been called. + bool get isClosed => _closeGroup != null; + /// Creates a new pool with the given limit on how many resources may be /// allocated at once. /// @@ -69,6 +79,10 @@ class Pool { /// If the maximum number of resources is already allocated, this will delay /// until one of them is released. Future request() { + if (isClosed) { + throw new StateError("request() may not be called on a closed Pool."); + } + if (_allocatedResources < _maxAllocatedResources) { _allocatedResources++; return new Future.value(new PoolResource._(this)); @@ -87,20 +101,56 @@ class Pool { /// /// The return value of [callback] is piped to the returned Future. Future withResource(callback()) { - return request().then((resource) => new Future.sync(callback).whenComplete(resource.release)); + if (isClosed) { + throw new StateError( + "withResource() may not be called on a closed Pool."); + } + + // TODO(nweiz): Use async/await when sdk#23497 is fixed. + return request().then((resource) { + return new Future.sync(callback).whenComplete(resource.release); + }); + } + + /// Closes the pool so that no more resources are requested. + /// + /// Existing resource requests remain unchanged. + /// + /// Any resources that are marked as releasable using + /// [PoolResource.allowRelease] are released immediately. Once all resources + /// have been released and any `onRelease` callbacks have completed, the + /// returned future completes successfully. If any `onRelease` callback throws + /// an error, the returned future completes with that error. + /// + /// This may be called more than once; it returns the same [Future] each time. + Future close() { + if (_closeGroup != null) return _closeGroup.future; + + _resetTimer(); + + _closeGroup = new FutureGroup(); + for (var callback in _onReleaseCallbacks) { + _closeGroup.add(new Future.sync(callback)); + } + + _allocatedResources -= _onReleaseCallbacks.length; + _onReleaseCallbacks.clear(); + + if (_allocatedResources == 0) _closeGroup.close(); + return _closeGroup.future; } /// If there are any pending requests, this will fire the oldest one. void _onResourceReleased() { _resetTimer(); - if (_requestedResources.isEmpty) { + if (_requestedResources.isNotEmpty) { + var pending = _requestedResources.removeFirst(); + pending.complete(new PoolResource._(this)); + } else { _allocatedResources--; - return; + if (isClosed && _allocatedResources == 0) _closeGroup.close(); } - - var pending = _requestedResources.removeFirst(); - pending.complete(new PoolResource._(this)); } /// If there are any pending requests, this will fire the oldest one after @@ -108,14 +158,17 @@ class Pool { void _onResourceReleaseAllowed(onRelease()) { _resetTimer(); - if (_requestedResources.isEmpty) { + if (_requestedResources.isNotEmpty) { + var pending = _requestedResources.removeFirst(); + pending.complete(_runOnRelease(onRelease)); + } else if (isClosed) { + _closeGroup.add(new Future.sync(onRelease)); + _allocatedResources--; + if (_allocatedResources == 0) _closeGroup.close(); + } else { _onReleaseCallbacks.add( Zone.current.bindCallback(onRelease, runGuarded: false)); - return; } - - var pending = _requestedResources.removeFirst(); - pending.complete(_runOnRelease(onRelease)); } /// Runs [onRelease] and returns a Future that completes to a resource once an @@ -202,4 +255,3 @@ class PoolResource { _pool._onResourceReleaseAllowed(onRelease); } } - diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index cc2d367be..0013e9e2e 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,9 +1,10 @@ name: pool -version: 1.1.1-dev +version: 1.2.0 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool dependencies: + async: "^1.3.0" stack_trace: ">=0.9.2 <2.0.0" environment: sdk: ">=1.9.0 <2.0.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 5dfef2a24..65fd00ee2 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -271,6 +271,139 @@ void main() { pool.request(); }); }); + + group("close()", () { + test("disallows request() and withResource()", () { + var pool = new Pool(1)..close(); + expect(pool.request, throwsStateError); + expect(() => pool.withResource(() {}), throwsStateError); + }); + + test("pending requests are fulfilled", () async { + var pool = new Pool(1); + var resource1 = await pool.request(); + expect(pool.request().then((resource2) { + resource2.release(); + }), completes); + expect(pool.close(), completes); + resource1.release(); + }); + + test("pending requests are fulfilled with allowRelease", () async { + var pool = new Pool(1); + var resource1 = await pool.request(); + + var completer = new Completer(); + expect(pool.request().then((resource2) { + expect(completer.isCompleted, isTrue); + resource2.release(); + }), completes); + expect(pool.close(), completes); + + resource1.allowRelease(() => completer.future); + await new Future.delayed(Duration.ZERO); + + completer.complete(); + }); + + test("doesn't complete until all resources are released", () async { + var pool = new Pool(2); + var resource1 = await pool.request(); + var resource2 = await pool.request(); + var resource3Future = pool.request(); + + var resource1Released = false; + var resource2Released = false; + var resource3Released = false; + expect(pool.close().then((_) { + expect(resource1Released, isTrue); + expect(resource2Released, isTrue); + expect(resource3Released, isTrue); + }), completes); + + resource1Released = true; + resource1.release(); + await new Future.delayed(Duration.ZERO); + + resource2Released = true; + resource2.release(); + await new Future.delayed(Duration.ZERO); + + var resource3 = await resource3Future; + resource3Released = true; + resource3.release(); + }); + + test("active onReleases complete as usual", () async { + var pool = new Pool(1); + var resource = await pool.request(); + + // Set up an onRelease callback whose completion is controlled by + // [completer]. + var completer = new Completer(); + resource.allowRelease(() => completer.future); + expect(pool.request().then((_) { + expect(completer.isCompleted, isTrue); + }), completes); + + await new Future.delayed(Duration.ZERO); + pool.close(); + + await new Future.delayed(Duration.ZERO); + completer.complete(); + }); + + test("inactive onReleases fire", () async { + var pool = new Pool(2); + var resource1 = await pool.request(); + var resource2 = await pool.request(); + + var completer1 = new Completer(); + resource1.allowRelease(() => completer1.future); + var completer2 = new Completer(); + resource2.allowRelease(() => completer2.future); + + expect(pool.close().then((_) { + expect(completer1.isCompleted, isTrue); + expect(completer2.isCompleted, isTrue); + }), completes); + + await new Future.delayed(Duration.ZERO); + completer1.complete(); + + await new Future.delayed(Duration.ZERO); + completer2.complete(); + }); + + test("new allowReleases fire immediately", () async { + var pool = new Pool(1); + var resource = await pool.request(); + + var completer = new Completer(); + expect(pool.close().then((_) { + expect(completer.isCompleted, isTrue); + }), completes); + + await new Future.delayed(Duration.ZERO); + resource.allowRelease(() => completer.future); + + await new Future.delayed(Duration.ZERO); + completer.complete(); + }); + + test("an onRelease error is piped to the return value", () async { + var pool = new Pool(1); + var resource = await pool.request(); + + var completer = new Completer(); + resource.allowRelease(() => completer.future); + + expect(pool.close(), throwsA("oh no!")); + + await new Future.delayed(Duration.ZERO); + completer.completeError("oh no!"); + }); + }); } /// Returns a function that will cause the test to fail if it's called. From a166eafb1660b9891e67aa8b864db1d928313fcb Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 28 Oct 2015 14:47:31 -0700 Subject: [PATCH 055/281] Use the async package's new RestartableTimer class. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1415223004 . --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/lib/pool.dart | 31 ++++++++++++++++++++----------- pkgs/pool/pubspec.yaml | 4 ++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 9f74d07b4..dc852aa35 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.1 + +* Internal changes only. + ## 1.2.0 * Add `Pool.close()`, which forbids new resource requests and releases all diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 59b949e0e..ef3861418 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -46,12 +46,14 @@ class Pool { /// The timeout timer. /// - /// If [_timeout] isn't null, this timer is set as soon as the resource limit - /// is reached and is reset every time an resource is released or a new - /// resource is requested. If it fires, that indicates that the caller became - /// deadlocked, likely due to files waiting for additional files to be read - /// before they could be closed. - Timer _timer; + /// This timer is canceled as long as the pool is below the resource limit. + /// It's reset once the resource limit is reached and again every time an + /// resource is released or a new resource is requested. If it fires, that + /// indicates that the caller became deadlocked, likely due to files waiting + /// for additional files to be read before they could be closed. + /// + /// This is `null` if this pool shouldn't time out. + RestartableTimer _timer; /// The amount of time to wait before timing out the pending resources. final Duration _timeout; @@ -72,7 +74,13 @@ class Pool { /// all pending [request] futures will throw a [TimeoutException]. This is /// intended to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) - : _timeout = timeout; + : _timeout = timeout { + if (timeout != null) { + // Start the timer canceled since we only want to start counting down once + // we've run out of available resources. + _timer = new RestartableTimer(timeout, _onTimeout)..cancel(); + } + } /// Request a [PoolResource]. /// @@ -190,11 +198,12 @@ class Pool { /// A resource has been requested, allocated, or released. void _resetTimer() { - if (_timer != null) _timer.cancel(); - if (_timeout == null || _requestedResources.isEmpty) { - _timer = null; + if (_timer == null) return; + + if (_requestedResources.isEmpty) { + _timer.cancel(); } else { - _timer = new Timer(_timeout, _onTimeout); + _timer.reset(); } } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 0013e9e2e..963562007 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,10 @@ name: pool -version: 1.2.0 +version: 1.2.1 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool dependencies: - async: "^1.3.0" + async: "^1.4.0" stack_trace: ">=0.9.2 <2.0.0" environment: sdk: ">=1.9.0 <2.0.0" From 389ddb974a7df6e7b2a71490e657d5653103d6dc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 12 Jan 2016 17:22:16 -0800 Subject: [PATCH 056/281] Get rid of all the library tags. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1572383005 . --- pkgs/pool/lib/pool.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index ef3861418..3279160be 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -2,8 +2,6 @@ // 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 pool; - import 'dart:async'; import 'dart:collection'; From bc986bb59e04b72b046850a6d7bf2bfb2d0469b5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 31 Mar 2016 16:26:08 -0700 Subject: [PATCH 057/281] Fix strong mode warnings. R=jmesserly@google.com Review URL: https://codereview.chromium.org//1843303002 . --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/lib/pool.dart | 14 ++++++++------ pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index dc852aa35..9ad86d0a8 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.2 + +* Fix strong mode warnings and add generic method annotations. + ## 1.2.1 * Internal changes only. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 3279160be..f7bfd828b 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -106,16 +106,18 @@ class Pool { /// Future. /// /// The return value of [callback] is piped to the returned Future. - Future withResource(callback()) { + Future/**/ withResource/**/(/*=T*/ callback()) async { if (isClosed) { throw new StateError( "withResource() may not be called on a closed Pool."); } - // TODO(nweiz): Use async/await when sdk#23497 is fixed. - return request().then((resource) { - return new Future.sync(callback).whenComplete(resource.release); - }); + var resource = await request(); + try { + return await callback(); + } finally { + resource.release(); + } } /// Closes the pool so that no more resources are requested. @@ -189,7 +191,7 @@ class Pool { _onReleaseCompleters.removeFirst().completeError(error, stackTrace); }); - var completer = new Completer.sync(); + var completer = new Completer.sync(); _onReleaseCompleters.add(completer); return completer.future; } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 963562007..314ac044c 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.2.1 +version: 1.2.2 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 65fd00ee2..91e683310 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -276,7 +276,7 @@ void main() { test("disallows request() and withResource()", () { var pool = new Pool(1)..close(); expect(pool.request, throwsStateError); - expect(() => pool.withResource(() {}), throwsStateError); + expect(pool.withResource(() {}), throwsStateError); }); test("pending requests are fulfilled", () async { From fda1a0114d110bb5bcb1d2037ef3afac922dc3e8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 4 Apr 2016 15:44:05 -0700 Subject: [PATCH 058/281] Don't use async/await for Pool.withResource(). The async gap introduces a potential race condition. Closes dart-lang/pool#3 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1853273002 . --- pkgs/pool/CHANGELOG.md | 5 +++++ pkgs/pool/lib/pool.dart | 15 ++++++++------- pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 9 ++++++++- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 9ad86d0a8..70f914ba2 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.2.3 + +* Fix a bug in which `Pool.withResource()` could throw a `StateError` when + called immediately before closing the pool. + ## 1.2.2 * Fix strong mode warnings and add generic method annotations. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index f7bfd828b..deb53334b 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -106,18 +106,19 @@ class Pool { /// Future. /// /// The return value of [callback] is piped to the returned Future. - Future/**/ withResource/**/(/*=T*/ callback()) async { + Future/**/ withResource/**/(/*=T*/ callback()) { if (isClosed) { throw new StateError( "withResource() may not be called on a closed Pool."); } - var resource = await request(); - try { - return await callback(); - } finally { - resource.release(); - } + // We can't use async/await here because we need to start the request + // synchronously in case the pool is closed immediately afterwards. Async + // functions have an asynchronous gap between calling and running the body, + // and [close] could be called during that gap. See #3. + return request().then((resource) { + return new Future.sync(callback).whenComplete(resource.release); + }); } /// Closes the pool so that no more resources are requested. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 314ac044c..58321cfae 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.2.2 +version: 1.2.3 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 91e683310..bd44cb275 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -96,6 +96,13 @@ void main() { async.elapse(new Duration(seconds: 1)); }); }); + + // Regression test for #3. + test("can be called immediately before close()", () async { + var pool = new Pool(1); + pool.withResource(expectAsync(() {})); + await pool.close(); + }); }); group("with a timeout", () { @@ -276,7 +283,7 @@ void main() { test("disallows request() and withResource()", () { var pool = new Pool(1)..close(); expect(pool.request, throwsStateError); - expect(pool.withResource(() {}), throwsStateError); + expect(() => pool.withResource(() {}), throwsStateError); }); test("pending requests are fulfilled", () async { From 4b38a40721d812bf98dffba968db745972aeaa10 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 3 May 2016 16:27:14 -0700 Subject: [PATCH 059/281] Fix a new strong-mode error. R=jmesserly@google.com Review URL: https://codereview.chromium.org//1949803002 . --- pkgs/pool/.analysis_options | 2 ++ pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/lib/pool.dart | 4 ++-- pkgs/pool/pubspec.yaml | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 pkgs/pool/.analysis_options diff --git a/pkgs/pool/.analysis_options b/pkgs/pool/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/pool/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 70f914ba2..96d4c2f51 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.4 + +* Fix a strong-mode error. + ## 1.2.3 * Fix a bug in which `Pool.withResource()` could throw a `StateError` when diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index deb53334b..faa9f0e12 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -116,8 +116,8 @@ class Pool { // synchronously in case the pool is closed immediately afterwards. Async // functions have an asynchronous gap between calling and running the body, // and [close] could be called during that gap. See #3. - return request().then((resource) { - return new Future.sync(callback).whenComplete(resource.release); + return request().then/*>*/((resource) { + return new Future/**/.sync(callback).whenComplete(resource.release); }); } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 58321cfae..145df2bbf 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.2.3 +version: 1.2.4 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool From 469c2234b1281836646e658a225cf56d8aa2ebb1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 4 May 2016 11:27:29 -0700 Subject: [PATCH 060/281] dartfmt --- pkgs/package_config/lib/discovery.dart | 8 +- .../lib/discovery_analysis.dart | 9 +- pkgs/package_config/lib/packages.dart | 1 - pkgs/package_config/lib/packages_file.dart | 2 +- .../package_config/lib/src/packages_impl.dart | 10 +- .../lib/src/packages_io_impl.dart | 9 +- pkgs/package_config/lib/src/util.dart | 28 ++-- .../test/discovery_analysis_test.dart | 37 ++--- pkgs/package_config/test/discovery_test.dart | 152 ++++++++---------- pkgs/package_config/test/parse_test.dart | 44 +++-- .../package_config/test/parse_write_test.dart | 15 +- 11 files changed, 151 insertions(+), 164 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 8e42af79d..10dbb8ef4 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -28,7 +28,7 @@ import "src/packages_io_impl.dart"; /// resolution file, for example one specified using a `--packages` /// command-line parameter. Future loadPackagesFile(Uri packagesFile, - {Future> loader(Uri uri)}) { + {Future> loader(Uri uri)}) { Packages parseBytes(List bytes) { Map packageMap = pkgfile.parse(bytes, packagesFile); return new MapPackages(packageMap); @@ -43,7 +43,6 @@ Future loadPackagesFile(Uri packagesFile, return loader(packagesFile).then(parseBytes); } - /// Create a [Packages] object for a package directory. /// /// The [packagesDir] URI should refer to a directory. @@ -63,7 +62,6 @@ Packages getPackagesDirectory(Uri packagesDir) { return new NonFilePackagesDirectoryPackages(packagesDir); } - /// Discover the package configuration for a Dart script. /// /// The [baseUri] points to either the Dart script or its directory. @@ -93,7 +91,7 @@ Packages getPackagesDirectory(Uri packagesDir) { /// The content should be a UTF-8 encoded `.packages` file, and must return an /// error future if loading fails for any reason. Future findPackages(Uri baseUri, - {Future> loader(Uri unsupportedUri)}) { + {Future> loader(Uri unsupportedUri)}) { if (baseUri.scheme == "file") { return new Future.sync(() => findPackagesFromFile(baseUri)); } else if (loader != null) { @@ -191,7 +189,7 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// of the requested `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) { + {Future> loader(Uri name)}) { if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); return loader(packagesFileUri).then((List fileBytes) { diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index af4df070a..6d4b9edd7 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -41,7 +41,7 @@ abstract class PackageContext { /// Look up the [PackageContext] that applies to a specific directory. /// /// The directory must be inside [directory]. - PackageContext operator[](Directory directory); + PackageContext operator [](Directory directory); /// A map from directory to package resolver. /// @@ -57,7 +57,7 @@ abstract class PackageContext { /// directory of `directory`. If there is, its corresponding `Packages` object /// should be provided as `root`. static PackageContext findAll(Directory directory, - {Packages root: Packages.noPackages}) { + {Packages root: Packages.noPackages}) { if (!directory.existsSync()) { throw new ArgumentError("Directory not found: $directory"); } @@ -93,8 +93,7 @@ abstract class PackageContext { } findRoots(directory); // If the root is not itself context root, add a the wrapper context. - if (contexts.length == 1 && - contexts[0].directory == directory) { + if (contexts.length == 1 && contexts[0].directory == directory) { return contexts[0]; } return new _PackageContext(directory, root, contexts); @@ -120,7 +119,7 @@ class _PackageContext implements PackageContext { return result; } - PackageContext operator[](Directory directory) { + PackageContext operator [](Directory directory) { String path = directory.path; if (!path.startsWith(this.directory.path)) { throw new ArgumentError("Not inside $path: $directory"); diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart index dbaa06dfd..890f4485c 100644 --- a/pkgs/package_config/lib/packages.dart +++ b/pkgs/package_config/lib/packages.dart @@ -17,7 +17,6 @@ import "src/packages_impl.dart"; /// One such case is if the packages are resolved relative to a /// `packages/` directory available over HTTP. abstract class Packages { - /// A [Packages] resolver containing no packages. /// /// This constant object is returned by [find] above if no diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index f30781dc3..93ccd3c18 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -84,7 +84,7 @@ Map parse(List source, Uri baseLocation) { /// All the keys of [packageMapping] must be valid package names, /// and the values must be URIs that do not have the `package:` scheme. void write(StringSink output, Map packageMapping, - {Uri baseUri, String comment}) { + {Uri baseUri, String comment}) { if (baseUri != null && !baseUri.isAbsolute) { throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); } diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index e85f75581..fa9115fc6 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -18,13 +18,13 @@ class NoPackages implements Packages { Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { String packageName = checkValidPackageUri(packageUri); if (notFound != null) return notFound(packageUri); - throw new ArgumentError.value(packageUri, "packageUri", - 'No package named "$packageName"'); + throw new ArgumentError.value( + packageUri, "packageUri", 'No package named "$packageName"'); } Iterable get packages => new Iterable.generate(0); - Map asMap() => const{}; + Map asMap() => const {}; } /// Base class for [Packages] implementations. @@ -38,8 +38,8 @@ abstract class PackagesBase implements Packages { Uri packageBase = getBase(packageName); if (packageBase == null) { if (notFound != null) return notFound(packageUri); - throw new ArgumentError.value(packageUri, "packageUri", - 'No package named "$packageName"'); + throw new ArgumentError.value( + packageUri, "packageUri", 'No package named "$packageName"'); } String packagePath = packageUri.path.substring(packageName.length + 1); return packageBase.resolve(packagePath); diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart index 21b61fdab..db39bdb58 100644 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -17,12 +17,13 @@ class FilePackagesDirectoryPackages extends PackagesBase { FilePackagesDirectoryPackages(this._packageDir); Uri getBase(String packageName) => - new Uri.file(path.join(_packageDir.path, packageName, '.')); + new Uri.file(path.join(_packageDir.path, packageName, '.')); Iterable _listPackageNames() { - return _packageDir.listSync() - .where((e) => e is Directory) - .map((e) => path.basename(e.path)); + return _packageDir + .listSync() + .where((e) => e is Directory) + .map((e) => path.basename(e.path)); } Iterable get packages => _listPackageNames(); diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index badf64086..f1e1afd0a 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -43,29 +43,29 @@ int _findInvalidCharacter(String string) { /// Validate that a Uri is a valid package:URI. String checkValidPackageUri(Uri packageUri) { if (packageUri.scheme != "package") { - throw new ArgumentError.value(packageUri, "packageUri", - "Not a package: URI"); + throw new ArgumentError.value( + packageUri, "packageUri", "Not a package: URI"); } if (packageUri.hasAuthority) { - throw new ArgumentError.value(packageUri, "packageUri", - "Package URIs must not have a host part"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package URIs must not have a host part"); } if (packageUri.hasQuery) { // A query makes no sense if resolved to a file: URI. - throw new ArgumentError.value(packageUri, "packageUri", - "Package URIs must not have a query part"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package URIs must not have a query part"); } if (packageUri.hasFragment) { // We could leave the fragment after the URL when resolving, // but it would be odd if "package:foo/foo.dart#1" and // "package:foo/foo.dart#2" were considered different libraries. // Keep the syntax open in case we ever get multiple libraries in one file. - throw new ArgumentError.value(packageUri, "packageUri", - "Package URIs must not have a fragment part"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package URIs must not have a fragment part"); } if (packageUri.path.startsWith('/')) { - throw new ArgumentError.value(packageUri, "packageUri", - "Package URIs must not start with a '/'"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package URIs must not start with a '/'"); } int firstSlash = packageUri.path.indexOf('/'); if (firstSlash == -1) { @@ -76,8 +76,8 @@ String checkValidPackageUri(Uri packageUri) { int badIndex = _findInvalidCharacter(packageName); if (badIndex >= 0) { if (packageName.isEmpty) { - throw new ArgumentError.value(packageUri, "packageUri", - "Package names mus be non-empty"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package names mus be non-empty"); } if (badIndex == packageName.length) { throw new ArgumentError.value(packageUri, "packageUri", @@ -90,8 +90,8 @@ String checkValidPackageUri(Uri packageUri) { // Printable character. badChar = "'${packageName[badIndex]}' ($badChar)"; } - throw new ArgumentError.value(packageUri, "packageUri", - "Package names must not contain $badChar"); + throw new ArgumentError.value( + packageUri, "packageUri", "Package names must not contain $badChar"); } return packageName; } diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart index f33a4a8c6..0a2876726 100644 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -13,12 +13,14 @@ import "package:path/path.dart" as path; import "package:test/test.dart"; main() { - fileTest("basic", - {".packages": packagesFile, - "foo": {".packages": packagesFile}, - "bar": {"packages": {"foo": {}, "bar":{}, "baz": {}}}, - "baz": {}}, - (Directory directory) { + fileTest("basic", { + ".packages": packagesFile, + "foo": {".packages": packagesFile}, + "bar": { + "packages": {"foo": {}, "bar": {}, "baz": {}} + }, + "baz": {} + }, (Directory directory) { var dirUri = new Uri.directory(directory.path); PackageContext ctx = PackageContext.findAll(directory); PackageContext root = ctx[directory]; @@ -32,13 +34,13 @@ main() { PackageContext bar = ctx[sub(directory, "bar")]; validatePackagesDir(bar.packages, dirUri.resolve("bar/")); PackageContext barbar = ctx[sub(barDir, "bar")]; - expect(barbar, same(bar)); // inherited. + expect(barbar, same(bar)); // inherited. PackageContext baz = ctx[sub(directory, "baz")]; - expect(baz, same(root)); // inherited. + expect(baz, same(root)); // inherited. var map = ctx.asMap(); expect(map.keys.map((dir) => dir.path), - unorderedEquals([directory.path, fooDir.path, barDir.path])); + unorderedEquals([directory.path, fooDir.path, barDir.path])); }); } @@ -56,11 +58,11 @@ baz:packages/baz/ void validatePackagesFile(Packages resolver, Uri location) { expect(resolver, isNotNull); expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); + equals(location.resolve("packages/baz/qux/foo"))); expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } @@ -68,11 +70,11 @@ void validatePackagesDir(Packages resolver, Uri location) { // Expect three packages: foo, bar and baz expect(resolver, isNotNull); expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); + equals(location.resolve("packages/foo/bar/baz"))); expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); + equals(location.resolve("packages/bar/baz/qux"))); expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); + equals(location.resolve("packages/baz/qux/foo"))); if (location.scheme == "file") { expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } else { @@ -95,9 +97,8 @@ Uri pkg(String packageName, String packagePath) { /// Description is a map, each key is a file entry. If the value is a map, /// it's a sub-dir, otherwise it's a file and the value is the content /// as a string. -void fileTest(String name, - Map description, - Future fileTest(Directory directory)) { +void fileTest( + String name, Map description, Future fileTest(Directory directory)) { group("file-test", () { Directory tempDir = Directory.systemTemp.createTempSync("file-test"); setUp(() { diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 4f780c2ad..97b7bbf91 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -21,11 +21,11 @@ baz:packages/baz/ void validatePackagesFile(Packages resolver, Uri location) { expect(resolver, isNotNull); expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); + equals(location.resolve("packages/baz/qux/foo"))); expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } @@ -33,11 +33,11 @@ void validatePackagesDir(Packages resolver, Uri location) { // Expect three packages: foo, bar and baz expect(resolver, isNotNull); expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); + equals(location.resolve("packages/foo/bar/baz"))); expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); + equals(location.resolve("packages/bar/baz/qux"))); expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); + equals(location.resolve("packages/baz/qux/foo"))); if (location.scheme == "file") { expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } else { @@ -45,7 +45,6 @@ void validatePackagesDir(Packages resolver, Uri location) { } } - Uri pkg(String packageName, String packagePath) { var path; if (packagePath.startsWith('/')) { @@ -57,11 +56,11 @@ Uri pkg(String packageName, String packagePath) { } main() { - generalTest(".packages", - {".packages": packagesFile, - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}}}, - (Uri location) async { + generalTest(".packages", { + ".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}} + }, (Uri location) async { Packages resolver; resolver = await findPackages(location); validatePackagesFile(resolver, location); @@ -76,36 +75,36 @@ main() { validatePackagesFile(resolver, location); }); - generalTest("packages/", - {"packages": { "foo": {}, "bar": {}, "baz": {}}, - "script.dart": "main(){}"}, - (Uri location) async { + generalTest("packages/", { + "packages": {"foo": {}, "bar": {}, "baz": {}}, + "script.dart": "main(){}" + }, (Uri location) async { Packages resolver; bool isFile = (location.scheme == "file"); resolver = await findPackages(location); validatePackagesDir(resolver, location); resolver = await findPackages(location.resolve("script.dart")); validatePackagesDir(resolver, location); - var specificDiscovery = isFile - ? findPackagesFromFile - : findPackagesFromNonFile; + var specificDiscovery = + isFile ? findPackagesFromFile : findPackagesFromNonFile; resolver = await specificDiscovery(location); validatePackagesDir(resolver, location); resolver = await specificDiscovery(location.resolve("script.dart")); validatePackagesDir(resolver, location); }); - generalTest("underscore packages", - {"packages": {"_foo": {}}}, - (Uri location) async { + generalTest("underscore packages", { + "packages": {"_foo": {}} + }, (Uri location) async { Packages resolver = await findPackages(location); expect(resolver.resolve(pkg("_foo", "foo.dart")), - equals(location.resolve("packages/_foo/foo.dart"))); + equals(location.resolve("packages/_foo/foo.dart"))); }); - fileTest(".packages recursive", - {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, - (Uri location) async { + fileTest(".packages recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Uri location) async { Packages resolver; resolver = await findPackages(location.resolve("subdir/")); validatePackagesFile(resolver, location); @@ -118,9 +117,10 @@ main() { validatePackagesFile(resolver, location); }); - httpTest(".packages not recursive", - {".packages": packagesFile, "subdir": {"script.dart": "main(){}"}}, - (Uri location) async { + httpTest(".packages not recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Uri location) async { Packages resolver; var subdir = location.resolve("subdir/"); resolver = await findPackages(subdir); @@ -133,9 +133,7 @@ main() { validatePackagesDir(resolver, subdir); }); - fileTest("no packages", - {"script.dart": "main(){}"}, - (Uri location) async { + fileTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { // A file: location with no .packages or packages returns // Packages.noPackages. Packages resolver; @@ -149,9 +147,7 @@ main() { expect(resolver, same(Packages.noPackages)); }); - httpTest("no packages", - {"script.dart": "main(){}"}, - (Uri location) async { + httpTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { // A non-file: location with no .packages or packages/: // Assumes a packages dir exists, and resolves relative to that. Packages resolver; @@ -178,13 +174,13 @@ main() { Packages resolver; resolver = await findPackages(location, loader: loader); validatePackagesFile(resolver, location); - resolver = await findPackages(location.resolve("script.dart"), - loader: loader); + resolver = + await findPackages(location.resolve("script.dart"), loader: loader); validatePackagesFile(resolver, location); resolver = await findPackagesFromNonFile(location, loader: loader); validatePackagesFile(resolver, location); resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader: loader); + loader: loader); validatePackagesFile(resolver, location); }); @@ -198,27 +194,26 @@ main() { Packages resolver; resolver = await findPackages(location, loader: loader); validatePackagesDir(resolver, location); - resolver = await findPackages(location.resolve("script.dart"), - loader: loader); + resolver = + await findPackages(location.resolve("script.dart"), loader: loader); validatePackagesDir(resolver, location); resolver = await findPackagesFromNonFile(location, loader: loader); validatePackagesDir(resolver, location); resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader:loader); + loader: loader); validatePackagesDir(resolver, location); }); - generalTest("loadPackagesFile", - {".packages": packagesFile}, - (Uri directory) async { + generalTest("loadPackagesFile", {".packages": packagesFile}, + (Uri directory) async { Uri file = directory.resolve(".packages"); Packages resolver = await loadPackagesFile(file); validatePackagesFile(resolver, file); }); - generalTest("loadPackagesFile non-default name", - {"pheldagriff": packagesFile}, - (Uri directory) async { + generalTest( + "loadPackagesFile non-default name", {"pheldagriff": packagesFile}, + (Uri directory) async { Uri file = directory.resolve("pheldagriff"); Packages resolver = await loadPackagesFile(file); validatePackagesFile(resolver, file); @@ -231,26 +226,23 @@ main() { validatePackagesFile(resolver, file); }); - generalTest("loadPackagesFile not found", - {}, - (Uri directory) async { + generalTest("loadPackagesFile not found", {}, (Uri directory) async { Uri file = directory.resolve(".packages"); expect(loadPackagesFile(file), throws); }); - generalTest("loadPackagesFile syntax error", - {".packages": "syntax error"}, - (Uri directory) async { + generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, + (Uri directory) async { Uri file = directory.resolve(".packages"); expect(loadPackagesFile(file), throws); }); - generalTest("getPackagesDir", - {"packages": {"foo": {}, "bar": {}, "baz": {}}}, - (Uri directory) async { + generalTest("getPackagesDir", { + "packages": {"foo": {}, "bar": {}, "baz": {}} + }, (Uri directory) async { Uri packages = directory.resolve("packages/"); Packages resolver = getPackagesDirectory(packages); - Uri resolved = resolver.resolve(pkg("foo","flip/flop")); + Uri resolved = resolver.resolve(pkg("foo", "flip/flop")); expect(resolved, packages.resolve("foo/flip/flop")); }); } @@ -260,9 +252,7 @@ main() { /// Description is a map, each key is a file entry. If the value is a map, /// it's a sub-dir, otherwise it's a file and the value is the content /// as a string. -void fileTest(String name, - Map description, - Future fileTest(Uri directory)) { +void fileTest(String name, Map description, Future fileTest(Uri directory)) { group("file-test", () { Directory tempDir = Directory.systemTemp.createTempSync("file-test"); setUp(() { @@ -285,31 +275,27 @@ void httpTest(String name, Map description, Future httpTest(Uri directory)) { var serverSub; var uri; setUp(() { - return HttpServer - .bind(InternetAddress.LOOPBACK_IP_V4, 0) - .then((server) { - uri = new Uri(scheme: "http", - host: "127.0.0.1", - port: server.port, - path: "/"); - serverSub = server.listen((HttpRequest request) { - // No error handling. - var path = request.uri.path; - if (path.startsWith('/')) path = path.substring(1); - if (path.endsWith('/')) path = path.substring(0, path.length - 1); - var parts = path.split('/'); - var fileOrDir = description; - for (int i = 0; i < parts.length; i++) { - fileOrDir = fileOrDir[parts[i]]; - if (fileOrDir == null) { - request.response.statusCode = 404; - request.response.close(); - } + return HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) { + uri = new Uri( + scheme: "http", host: "127.0.0.1", port: server.port, path: "/"); + serverSub = server.listen((HttpRequest request) { + // No error handling. + var path = request.uri.path; + if (path.startsWith('/')) path = path.substring(1); + if (path.endsWith('/')) path = path.substring(0, path.length - 1); + var parts = path.split('/'); + var fileOrDir = description; + for (int i = 0; i < parts.length; i++) { + fileOrDir = fileOrDir[parts[i]]; + if (fileOrDir == null) { + request.response.statusCode = 404; + request.response.close(); } - request.response.write(fileOrDir); - request.response.close(); - }); + } + request.response.write(fileOrDir); + request.response.close(); }); + }); }); tearDown(() => serverSub.cancel()); test(name, () => httpTest(uri)); diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 8ed5c2eb7..7a2fce7e2 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -73,8 +73,7 @@ main() { test("multiple", () { var packages = doParse(multiRelativeSample, base); - expect( - packages.packages.toList()..sort(), equals(["bar", "foo"])); + expect(packages.packages.toList()..sort(), equals(["bar", "foo"])); expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), equals(base.resolve("../test/").resolve("bar/baz.dart"))); expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), @@ -135,33 +134,32 @@ Packages doParse(String sample, Uri baseUri) { } // Valid samples. -var emptySample = ""; -var commentOnlySample = "# comment only\n"; -var emptyLinesSample = "\n\n\r\n"; -var singleRelativeSample = "foo:../test/\n"; -var singleRelativeSampleNoSlash = "foo:../test\n"; +var emptySample = ""; +var commentOnlySample = "# comment only\n"; +var emptyLinesSample = "\n\n\r\n"; +var singleRelativeSample = "foo:../test/\n"; +var singleRelativeSampleNoSlash = "foo:../test\n"; var singleRelativeSampleNoNewline = "foo:../test/"; -var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; -var singleEmptyPathSample = "foo:\n"; -var singleAbsolutePathSample = "foo:/test/\n"; -var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; +var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; +var singleEmptyPathSample = "foo:\n"; +var singleAbsolutePathSample = "foo:/test/\n"; +var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; // All valid path segment characters in an URI. -var allValidChars = - r"!$&'()*+,-.0123456789;=" +var allValidChars = r"!$&'()*+,-.0123456789;=" r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; var allValidCharsSample = "${allValidChars}:../test/\n"; // Invalid samples. var invalid = [ - ":baz.dart", // empty. - "foobar=baz.dart", // no colon (but an equals, which is not the same) - ".:../test/", // dot segment - "..:../test/", // dot-dot segment - "...:../test/", // dot-dot-dot segment - "foo/bar:../test/", // slash in name - "/foo:../test/", // slash at start of name - "?:../test/", // invalid characters. - "[:../test/", // invalid characters. - "x#:../test/", // invalid characters. + ":baz.dart", // empty. + "foobar=baz.dart", // no colon (but an equals, which is not the same) + ".:../test/", // dot segment + "..:../test/", // dot-dot segment + "...:../test/", // dot-dot-dot segment + "foo/bar:../test/", // slash in name + "/foo:../test/", // slash at start of name + "?:../test/", // invalid characters. + "[:../test/", // invalid characters. + "x#:../test/", // invalid characters. ]; diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart index 6a185db20..29c2224a5 100644 --- a/pkgs/package_config/test/parse_write_test.dart +++ b/pkgs/package_config/test/parse_write_test.dart @@ -52,12 +52,17 @@ main() { roundTripTest("http directory", {"foo": httpDir}); roundTripTest("other scheme directory", {"foo": otherDir}); roundTripTest("multiple same-type directories", - {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); + {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); roundTripTest("multiple scheme directories", - {"foo": fileDir, "bar": httpDir, "baz": otherDir}); - roundTripTest("multiple scheme directories and mutliple same type", - {"foo": fileDir, "bar": httpDir, "baz": otherDir, - "qux": lowerDir, "hip": higherDir, "dep": parallelDir}); + {"foo": fileDir, "bar": httpDir, "baz": otherDir}); + roundTripTest("multiple scheme directories and mutliple same type", { + "foo": fileDir, + "bar": httpDir, + "baz": otherDir, + "qux": lowerDir, + "hip": higherDir, + "dep": parallelDir + }); }); } From 4cd7dfb3f6c0f528a5cb4baff7779a818d3a850b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 4 May 2016 11:31:07 -0700 Subject: [PATCH 061/281] strong-mode clean --- pkgs/package_config/.analysis_options | 2 ++ pkgs/package_config/lib/discovery_analysis.dart | 4 ++-- pkgs/package_config/test/discovery_test.dart | 6 +++--- pkgs/package_config/test/parse_write_test.dart | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 pkgs/package_config/.analysis_options diff --git a/pkgs/package_config/.analysis_options b/pkgs/package_config/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/package_config/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index 6d4b9edd7..058330b19 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -61,10 +61,10 @@ abstract class PackageContext { if (!directory.existsSync()) { throw new ArgumentError("Directory not found: $directory"); } - List contexts = []; + var contexts = []; void findRoots(Directory directory) { Packages packages; - List oldContexts; + List oldContexts; File packagesFile = new File(path.join(directory.path, ".packages")); if (packagesFile.existsSync()) { packages = _loadPackagesFile(packagesFile); diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 97b7bbf91..8807ac497 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -163,7 +163,7 @@ main() { test(".packages w/ loader", () async { Uri location = Uri.parse("krutch://example.com/path/"); - Future loader(Uri file) async { + Future> loader(Uri file) async { if (file.path.endsWith(".packages")) { return packagesFile.codeUnits; } @@ -186,7 +186,7 @@ main() { test("no packages w/ loader", () async { Uri location = Uri.parse("krutch://example.com/path/"); - Future loader(Uri file) async { + Future> loader(Uri file) async { throw "not found"; } // A non-file: location with no .packages or packages/: @@ -220,7 +220,7 @@ main() { }); test("loadPackagesFile w/ loader", () async { - loader(Uri uri) async => packagesFile.codeUnits; + Future> loader(Uri uri) async => packagesFile.codeUnits; Uri file = Uri.parse("krutz://example.com/.packages"); Packages resolver = await loadPackagesFile(file, loader: loader); validatePackagesFile(resolver, file); diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart index 29c2224a5..430218791 100644 --- a/pkgs/package_config/test/parse_write_test.dart +++ b/pkgs/package_config/test/parse_write_test.dart @@ -81,7 +81,7 @@ main() { }); } -String writeToString(Map map, {Uri baseUri, String comment}) { +String writeToString(Map map, {Uri baseUri, String comment}) { var buffer = new StringBuffer(); write(buffer, map, baseUri: baseUri, comment: comment); return buffer.toString(); From 019debf0c1f45c5d572329bdf399a0fe4f4719b3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 4 May 2016 11:32:13 -0700 Subject: [PATCH 062/281] cleanup gitignore --- pkgs/package_config/.gitignore | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index b46f3df8e..aac1f4fe8 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -1,8 +1,4 @@ -.idea +.packages .pub packages -build -.project -.settings pubspec.lock -.packages From 52f15c0fdbf5a791749335b1807d4dcdee4e0bae Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 4 May 2016 16:05:42 -0700 Subject: [PATCH 063/281] More strong-mode fixes --- pkgs/package_config/CHANGELOG.md | 11 +++++------ pkgs/package_config/lib/discovery.dart | 18 ++++++++++-------- pkgs/package_config/pubspec.yaml | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index f4e355e2c..6ac42ec58 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,16 +1,15 @@ -# Changelog +## 0.1.4 -## 0.1.3-dev +- Strong mode fixes. -- Invalid test cleanup (to keepup with changes in `Uri`). +## 0.1.3 + +- Invalid test cleanup (to keep up with changes in `Uri`). ## 0.1.1 - Syntax updates. - ## 0.1.0 - Initial implementation. - - diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 10dbb8ef4..4c09eecfb 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -28,19 +28,19 @@ import "src/packages_io_impl.dart"; /// resolution file, for example one specified using a `--packages` /// command-line parameter. Future loadPackagesFile(Uri packagesFile, - {Future> loader(Uri uri)}) { + {Future> loader(Uri uri)}) async { Packages parseBytes(List bytes) { Map packageMap = pkgfile.parse(bytes, packagesFile); return new MapPackages(packageMap); } if (packagesFile.scheme == "file") { File file = new File.fromUri(packagesFile); - return file.readAsBytes().then(parseBytes); + return parseBytes(await file.readAsBytes()); } if (loader == null) { - return _httpGet(packagesFile).then(parseBytes); + return parseBytes(await _httpGet(packagesFile)); } - return loader(packagesFile).then(parseBytes); + return parseBytes(await loader(packagesFile)); } /// Create a [Packages] object for a package directory. @@ -189,17 +189,19 @@ Packages findPackagesFromFile(Uri fileBaseUri) { /// of the requested `.packages` file as bytes, which will be assumed to be /// UTF-8 encoded. Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) { + {Future> loader(Uri name)}) async { if (loader == null) loader = _httpGet; Uri packagesFileUri = nonFileUri.resolve(".packages"); - return loader(packagesFileUri).then((List fileBytes) { + + try { + List fileBytes = await loader(packagesFileUri); Map map = pkgfile.parse(fileBytes, packagesFileUri); return new MapPackages(map); - }, onError: (_) { + } catch (_) { // Didn't manage to load ".packages". Assume a "packages/" directory. Uri packagesDirectoryUri = nonFileUri.resolve("packages/"); return new NonFilePackagesDirectoryPackages(packagesDirectoryUri); - }); + } } /// Fetches a file over http. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index f2c4e06cc..80aea6dd1 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.3 +version: 0.1.4 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 0e70668b1de4b464ab429a9453c50fd41837efd8 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 7 Jun 2016 18:49:55 -0700 Subject: [PATCH 064/281] Cache packageName to base Uri mapping. This makes analysis with using incremental analysis cache 30% faster. Without this change getBase() takes 40% (!) of total analysis time. With this change - just 0.79% of total time. Although the remaining 17% of PackagesBase.resolve() make my cry. Why URI manipulations are SO SLOW?! R=brianwilkerson@google.com, pquitslund@google.com, kevmoo@google.com BUG= Review URL: https://codereview.chromium.org/2041103005 . --- pkgs/package_config/lib/src/packages_io_impl.dart | 9 +++++++-- pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart index db39bdb58..0e9474639 100644 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -14,10 +14,15 @@ import "packages_impl.dart"; /// A [Packages] implementation based on a local directory. class FilePackagesDirectoryPackages extends PackagesBase { final Directory _packageDir; + final Map _packageToBaseUriMap = {}; + FilePackagesDirectoryPackages(this._packageDir); - Uri getBase(String packageName) => - new Uri.file(path.join(_packageDir.path, packageName, '.')); + Uri getBase(String packageName) { + return _packageToBaseUriMap.putIfAbsent(packageName, () { + return new Uri.file(path.join(_packageDir.path, packageName, '.')); + }); + } Iterable _listPackageNames() { return _packageDir diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 80aea6dd1..3d9bd45f9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.4 +version: 0.1.5 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 65b68c2597dd2325a113316698276b12ef2053a2 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 9 Jun 2016 09:00:57 -0700 Subject: [PATCH 065/281] `0.1.5` CHANGELOG update pre-publish. Adds: * FilePackagesDirectoryPackages.getBase(..)` performance improvements. BUG= R=scheglov@google.com Review URL: https://codereview.chromium.org//2051143002 . --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/codereview.settings | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 pkgs/package_config/codereview.settings diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 6ac42ec58..b7b441e9e 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5 + +- `FilePackagesDirectoryPackages.getBase(..)` performance improvements. + ## 0.1.4 - Strong mode fixes. diff --git a/pkgs/package_config/codereview.settings b/pkgs/package_config/codereview.settings new file mode 100644 index 000000000..1099f0594 --- /dev/null +++ b/pkgs/package_config/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: https://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/package_config/commit/ +CC_LIST: reviews@dartlang.org From 08cc6269bab6827b78d8b554582d16d925ceb000 Mon Sep 17 00:00:00 2001 From: pq Date: Tue, 14 Jun 2016 09:37:11 -0700 Subject: [PATCH 066/281] Bump `package_config` to 1.0.0. BUG= R=lrn@google.com Review URL: https://codereview.chromium.org//2061863002 . --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index b7b441e9e..18a42ce71 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0 + +- Public API marked stable. + ## 0.1.5 - `FilePackagesDirectoryPackages.getBase(..)` performance improvements. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 3d9bd45f9..e1afec23c 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 0.1.5 +version: 1.0.0 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From afcf0d0f0309ae7b42e5ca2acee24c3b41f722d2 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Tue, 16 Aug 2016 17:53:12 +0100 Subject: [PATCH 067/281] Remove space that causes link not to render on pub.dartlang.org. The link doesn't render correctly here because of the space: https://pub.dartlang.org/packages/package_config --- pkgs/package_config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 0463719b3..942822002 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -2,7 +2,7 @@ Support for working with **Package Resolution Configuration** files as described in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), -under review [here] (https://github.com/dart-lang/dart_enhancement_proposals/issues/5). +under review [here](https://github.com/dart-lang/dart_enhancement_proposals/issues/5). [![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) From fe0d59a2a6353f8aa2d961327f91e91847919ab4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 2 Sep 2016 07:04:05 -0700 Subject: [PATCH 068/281] Some minor changes: - organize imports - add the generated doc directory to the gitignore file BUG= R=pquitslund@google.com Review URL: https://codereview.chromium.org//2298063005 . --- pkgs/package_config/.gitignore | 1 + pkgs/package_config/lib/discovery_analysis.dart | 2 +- pkgs/package_config/lib/packages_file.dart | 1 + pkgs/package_config/lib/src/packages_impl.dart | 1 + pkgs/package_config/lib/src/packages_io_impl.dart | 2 ++ 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index aac1f4fe8..a8b93ef38 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -2,3 +2,4 @@ .pub packages pubspec.lock +doc/api/ diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index 058330b19..ce7e98a1a 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -12,8 +12,8 @@ /// determined to be "package directories" themselves. library package_config.discovery_analysis; -import "dart:io" show File, Directory; import "dart:collection" show HashMap; +import "dart:io" show File, Directory; import "package:path/path.dart" as path; diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 93ccd3c18..0f1a6e635 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -5,6 +5,7 @@ library package_config.packages_file; import "package:charcode/ascii.dart"; + import "src/util.dart" show isValidPackageName; /// Parses a `.packages` file into a map from package name to base URI. diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index fa9115fc6..df89e4623 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -8,6 +8,7 @@ library package_config.packages_impl; import "dart:collection" show UnmodifiableMapView; + import "../packages.dart"; import "util.dart" show checkValidPackageUri; diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart index 0e9474639..9eba9ce44 100644 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -8,7 +8,9 @@ library package_config.packages_io_impl; import "dart:collection" show UnmodifiableMapView; import "dart:io" show Directory; + import "package:path/path.dart" as path; + import "packages_impl.dart"; /// A [Packages] implementation based on a local directory. From 11e3f8c83b99f12b6a265970c95ed35aa5a37280 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Feb 2017 13:10:41 -0800 Subject: [PATCH 069/281] Add a Pool.done getter. (dart-lang/pool#5) --- pkgs/pool/CHANGELOG.md | 5 +++++ pkgs/pool/lib/pool.dart | 14 +++++++++++--- pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 12 ++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 96d4c2f51..66b476920 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.3.0 + +* Add a `Pool.done` getter that returns the same future returned by + `Pool.close()`. + ## 1.2.4 * Fix a strong-mode error. diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index faa9f0e12..67c4a8287 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -63,7 +63,14 @@ class Pool { FutureGroup _closeGroup; /// Whether [close] has been called. - bool get isClosed => _closeGroup != null; + bool get isClosed => _closeMemo.hasRun; + + /// A future that completes once the pool is closed and all its outstanding + /// resources have been released. + /// + /// If any [PoolResource.allowRelease] callback throws an exception after the + /// pool is closed, this completes with that exception. + Future get done => _closeMemo.future; /// Creates a new pool with the given limit on how many resources may be /// allocated at once. @@ -132,7 +139,7 @@ class Pool { /// an error, the returned future completes with that error. /// /// This may be called more than once; it returns the same [Future] each time. - Future close() { + Future close() => _closeMemo.runOnce(() { if (_closeGroup != null) return _closeGroup.future; _resetTimer(); @@ -147,7 +154,8 @@ class Pool { if (_allocatedResources == 0) _closeGroup.close(); return _closeGroup.future; - } + }); + final _closeMemo = new AsyncMemoizer(); /// If there are any pending requests, this will fire the oldest one. void _onResourceReleased() { diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 145df2bbf..3029b9fc4 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.2.4 +version: 1.3.0 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index bd44cb275..7fba9c0b0 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -279,6 +279,16 @@ void main() { }); }); + test("done doesn't complete without close", () async { + var pool = new Pool(1); + pool.done.then(expectAsync1((_) {}, count: 0)); + + var resource = await pool.request(); + resource.release(); + + await new Future.delayed(Duration.ZERO); + }); + group("close()", () { test("disallows request() and withResource()", () { var pool = new Pool(1)..close(); @@ -292,6 +302,7 @@ void main() { expect(pool.request().then((resource2) { resource2.release(); }), completes); + expect(pool.done, completes); expect(pool.close(), completes); resource1.release(); }); @@ -405,6 +416,7 @@ void main() { var completer = new Completer(); resource.allowRelease(() => completer.future); + expect(pool.done, throwsA("oh no!")); expect(pool.close(), throwsA("oh no!")); await new Future.delayed(Duration.ZERO); From 520ade132d7397f7f180a171d387f796b4718af6 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 4 May 2017 16:13:41 +0200 Subject: [PATCH 070/281] Fix write to sink after close in test code. R=floitsch@google.com Review-Url: https://codereview.chromium.org//2857383002 . --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 18a42ce71..c03367853 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +- Fix test to not write to sink after it's closed. + ## 1.0.0 - Public API marked stable. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index e1afec23c..eaef83e3a 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.0.0 +version: 1.0.1 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 8807ac497..897063f52 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -290,6 +290,7 @@ void httpTest(String name, Map description, Future httpTest(Uri directory)) { if (fileOrDir == null) { request.response.statusCode = 404; request.response.close(); + return; } } request.response.write(fileOrDir); From c289d1c07a23f780988040875385ff7ab3a955e9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 16 May 2017 20:43:35 -0700 Subject: [PATCH 071/281] Pool.withResource() should take () -> FutureOr. (dart-lang/pool#7) Closes dart-lang/pool#6 --- pkgs/pool/CHANGELOG.md | 5 +++++ pkgs/pool/lib/pool.dart | 6 +++--- pkgs/pool/pubspec.yaml | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 66b476920..80d54c73f 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.3.1 + +* Fix the type annotation of `Pool.withResource()` to indicate that it takes + `() -> FutureOr`. + ## 1.3.0 * Add a `Pool.done` getter that returns the same future returned by diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 67c4a8287..04aaaea65 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -113,7 +113,7 @@ class Pool { /// Future. /// /// The return value of [callback] is piped to the returned Future. - Future/**/ withResource/**/(/*=T*/ callback()) { + Future withResource(FutureOr callback()) { if (isClosed) { throw new StateError( "withResource() may not be called on a closed Pool."); @@ -123,8 +123,8 @@ class Pool { // synchronously in case the pool is closed immediately afterwards. Async // functions have an asynchronous gap between calling and running the body, // and [close] could be called during that gap. See #3. - return request().then/*>*/((resource) { - return new Future/**/.sync(callback).whenComplete(resource.release); + return request().then>((resource) { + return new Future.sync(callback).whenComplete(resource.release); }); } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 3029b9fc4..8efc8e55a 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.0 +version: 1.3.1 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool @@ -7,7 +7,7 @@ dependencies: async: "^1.4.0" stack_trace: ">=0.9.2 <2.0.0" environment: - sdk: ">=1.9.0 <2.0.0" + sdk: ">=1.22.0 <2.0.0" dev_dependencies: fake_async: ">=0.1.0 <0.2.0" test: ">=0.12.0 <0.13.0" From 4b603539a0568f653b689cea40de435b8cc17f53 Mon Sep 17 00:00:00 2001 From: David Morgan Date: Wed, 5 Jul 2017 22:45:45 +0200 Subject: [PATCH 072/281] Update README.md (dart-lang/pool#8) --- pkgs/pool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/README.md b/pkgs/pool/README.md index 898728867..641e77287 100644 --- a/pkgs/pool/README.md +++ b/pkgs/pool/README.md @@ -13,7 +13,7 @@ final pool = new Pool(10, timeout: new Duration(seconds: 30)); Future readFile(String path) { // Since the call to [File.readAsString] is within [withResource], no more // than ten files will be open at once. - return pool.withResource(() => return new File(path).readAsString()); + return pool.withResource(() => new File(path).readAsString()); } ``` From e7805eaf4c4b21af38c2c9d72e78e092d1242761 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 19 Jul 2017 12:08:29 -0700 Subject: [PATCH 073/281] Update SDK constraint to be 2.0.0 dev friendly. --- pkgs/package_config/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index eaef83e3a..a629eafef 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,15 +1,15 @@ name: package_config -version: 1.0.1 +version: 1.0.2 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=1.11.0-dev.0.0 <2.0.0' + sdk: '>=1.11.0 <2.0.0-dev.infinity' dependencies: charcode: ^1.1.0 path: ^1.0.0 dev_dependencies: - test: '>=0.12.0 <0.13.0' + test: ^0.12.0 From 4160a04201c62ea197f4df9ab0b4007dfc255237 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 19 Jul 2017 12:10:16 -0700 Subject: [PATCH 074/281] Update CHANGELOG.md --- pkgs/package_config/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index c03367853..c17c67498 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2 + +- Update SDK constraint to be 2.0.0 dev friendly. + ## 1.0.1 - Fix test to not write to sink after it's closed. From 9d1c4cc5a4ba9740ef46bbebeee73fe882e22f8a Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 19 Jul 2017 12:19:59 -0700 Subject: [PATCH 075/281] Rename .analysis_options to analysis_options.yaml --- pkgs/package_config/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/package_config/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/package_config/.analysis_options b/pkgs/package_config/analysis_options.yaml similarity index 100% rename from pkgs/package_config/.analysis_options rename to pkgs/package_config/analysis_options.yaml From 5312c5efd70ea519f5356b83cdfab355e2729d1b Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 3 Aug 2017 15:48:10 -0700 Subject: [PATCH 076/281] Make trusty default distro explicit. --- pkgs/package_config/.travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index 7a20d25b2..d7febddd1 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -1,4 +1,5 @@ language: dart dart: dev script: ./tool/travis.sh +dist: trusty sudo: false From 8f1ff683b44d236dfbc772d5e9711ae7395db768 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 20:35:48 -0700 Subject: [PATCH 077/281] Update to make the code work with strong-mode clean Zone API. --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/lib/pool.dart | 5 +++-- pkgs/pool/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 80d54c73f..63cf0069f 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.2 + +* Update to make the code work with strong-mode clean Zone API. + ## 1.3.1 * Fix the type annotation of `Pool.withResource()` to indicate that it takes diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 04aaaea65..d81386fa2 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -183,8 +183,9 @@ class Pool { _allocatedResources--; if (_allocatedResources == 0) _closeGroup.close(); } else { - _onReleaseCallbacks.add( - Zone.current.bindCallback(onRelease, runGuarded: false)); + var zone = Zone.current; + var registered = zone.registerCallback(onRelease); + _onReleaseCallbacks.add(() => zone.run(registered)); } } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 8efc8e55a..4a8271b87 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.1 +version: 1.3.2 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool From 002dcd781b10ac9211ba76bd0a8fadbbc9532dfd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 20:33:03 -0700 Subject: [PATCH 078/281] Move analysis_options file --- pkgs/pool/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/pool/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/pool/.analysis_options b/pkgs/pool/analysis_options.yaml similarity index 100% rename from pkgs/pool/.analysis_options rename to pkgs/pool/analysis_options.yaml From d61475c66b66f63e10faf3399025a7c4204834da Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 20:34:16 -0700 Subject: [PATCH 079/281] Add travis-ci config --- pkgs/pool/.travis.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 pkgs/pool/.travis.yml diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml new file mode 100644 index 000000000..b202aac3e --- /dev/null +++ b/pkgs/pool/.travis.yml @@ -0,0 +1,22 @@ +language: dart +sudo: false +dart: + - dev + - stable + - 1.22.0 + +dart_task: + - test: --platform vm + - test: --platform firefox + - test: --platform dartium + install_dartium: true + - dartfmt + - dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From d955b75554d8e66762e1d2cc957fc748adc98cf5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 20:40:44 -0700 Subject: [PATCH 080/281] dartfmt --- pkgs/pool/lib/pool.dart | 28 +++++++-------- pkgs/pool/test/pool_test.dart | 68 ++++++++++++++++++++--------------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index d81386fa2..86f8363ce 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -78,8 +78,7 @@ class Pool { /// If [timeout] is passed, then if that much time passes without any activity /// all pending [request] futures will throw a [TimeoutException]. This is /// intended to avoid deadlocks. - Pool(this._maxAllocatedResources, {Duration timeout}) - : _timeout = timeout { + Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout { if (timeout != null) { // Start the timer canceled since we only want to start counting down once // we've run out of available resources. @@ -140,21 +139,21 @@ class Pool { /// /// This may be called more than once; it returns the same [Future] each time. Future close() => _closeMemo.runOnce(() { - if (_closeGroup != null) return _closeGroup.future; + if (_closeGroup != null) return _closeGroup.future; - _resetTimer(); + _resetTimer(); - _closeGroup = new FutureGroup(); - for (var callback in _onReleaseCallbacks) { - _closeGroup.add(new Future.sync(callback)); - } + _closeGroup = new FutureGroup(); + for (var callback in _onReleaseCallbacks) { + _closeGroup.add(new Future.sync(callback)); + } - _allocatedResources -= _onReleaseCallbacks.length; - _onReleaseCallbacks.clear(); + _allocatedResources -= _onReleaseCallbacks.length; + _onReleaseCallbacks.clear(); - if (_allocatedResources == 0) _closeGroup.close(); - return _closeGroup.future; - }); + if (_allocatedResources == 0) _closeGroup.close(); + return _closeGroup.future; + }); final _closeMemo = new AsyncMemoizer(); /// If there are any pending requests, this will fire the oldest one. @@ -222,7 +221,8 @@ class Pool { void _onTimeout() { for (var completer in _requestedResources) { completer.completeError( - new TimeoutException("Pool deadlock: all resources have been " + new TimeoutException( + "Pool deadlock: all resources have been " "allocated for too long.", _timeout), new Chain.current()); diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 7fba9c0b0..6feba75c3 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -299,9 +299,11 @@ void main() { test("pending requests are fulfilled", () async { var pool = new Pool(1); var resource1 = await pool.request(); - expect(pool.request().then((resource2) { - resource2.release(); - }), completes); + expect( + pool.request().then((resource2) { + resource2.release(); + }), + completes); expect(pool.done, completes); expect(pool.close(), completes); resource1.release(); @@ -312,10 +314,12 @@ void main() { var resource1 = await pool.request(); var completer = new Completer(); - expect(pool.request().then((resource2) { - expect(completer.isCompleted, isTrue); - resource2.release(); - }), completes); + expect( + pool.request().then((resource2) { + expect(completer.isCompleted, isTrue); + resource2.release(); + }), + completes); expect(pool.close(), completes); resource1.allowRelease(() => completer.future); @@ -333,11 +337,13 @@ void main() { var resource1Released = false; var resource2Released = false; var resource3Released = false; - expect(pool.close().then((_) { - expect(resource1Released, isTrue); - expect(resource2Released, isTrue); - expect(resource3Released, isTrue); - }), completes); + expect( + pool.close().then((_) { + expect(resource1Released, isTrue); + expect(resource2Released, isTrue); + expect(resource3Released, isTrue); + }), + completes); resource1Released = true; resource1.release(); @@ -360,9 +366,11 @@ void main() { // [completer]. var completer = new Completer(); resource.allowRelease(() => completer.future); - expect(pool.request().then((_) { - expect(completer.isCompleted, isTrue); - }), completes); + expect( + pool.request().then((_) { + expect(completer.isCompleted, isTrue); + }), + completes); await new Future.delayed(Duration.ZERO); pool.close(); @@ -381,10 +389,12 @@ void main() { var completer2 = new Completer(); resource2.allowRelease(() => completer2.future); - expect(pool.close().then((_) { - expect(completer1.isCompleted, isTrue); - expect(completer2.isCompleted, isTrue); - }), completes); + expect( + pool.close().then((_) { + expect(completer1.isCompleted, isTrue); + expect(completer2.isCompleted, isTrue); + }), + completes); await new Future.delayed(Duration.ZERO); completer1.complete(); @@ -398,9 +408,11 @@ void main() { var resource = await pool.request(); var completer = new Completer(); - expect(pool.close().then((_) { - expect(completer.isCompleted, isTrue); - }), completes); + expect( + pool.close().then((_) { + expect(completer.isCompleted, isTrue); + }), + completes); await new Future.delayed(Duration.ZERO); resource.allowRelease(() => completer.future); @@ -438,10 +450,10 @@ Function expectNoAsync() { /// /// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { - expect(future, new isInstanceOf()); + expect(future, new isInstanceOf()); - var stack = new Trace.current(1); - future.then((_) => registerException( - new TestFailure("Expected future not to complete."), stack)); - return true; -}); + var stack = new Trace.current(1); + future.then((_) => registerException( + new TestFailure("Expected future not to complete."), stack)); + return true; + }); From d45732291af1f389c68c4359093841c37cacd37b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 20:57:07 -0700 Subject: [PATCH 081/281] Update minimum SDK --- pkgs/pool/.travis.yml | 2 +- pkgs/pool/CHANGELOG.md | 2 ++ pkgs/pool/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index b202aac3e..bf601a14f 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -3,7 +3,7 @@ sudo: false dart: - dev - stable - - 1.22.0 + - 1.23.0 dart_task: - test: --platform vm diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 63cf0069f..fbf12f2cb 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -2,6 +2,8 @@ * Update to make the code work with strong-mode clean Zone API. +* Required minimum SDK of 1.23.0. + ## 1.3.1 * Fix the type annotation of `Pool.withResource()` to indicate that it takes diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 4a8271b87..3c65826e2 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -7,7 +7,7 @@ dependencies: async: "^1.4.0" stack_trace: ">=0.9.2 <2.0.0" environment: - sdk: ">=1.22.0 <2.0.0" + sdk: ">=1.23.0 <2.0.0" dev_dependencies: fake_async: ">=0.1.0 <0.2.0" test: ">=0.12.0 <0.13.0" From ac2c0728aac408b177fd997ef170df830f881ba2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 12:05:30 -0700 Subject: [PATCH 082/281] Stop using deprecated pkg/test APIs - throw an HttpException ...instead of a String --- pkgs/package_config/lib/discovery.dart | 4 ++-- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_analysis_test.dart | 2 +- pkgs/package_config/test/discovery_test.dart | 9 ++++++--- pkgs/package_config/test/parse_test.dart | 8 +++++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 4c09eecfb..2abf443fb 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -210,8 +210,8 @@ Future> _httpGet(Uri uri) async { HttpClientRequest request = await client.getUrl(uri); HttpClientResponse response = await request.close(); if (response.statusCode != HttpStatus.OK) { - throw 'Failure getting $uri: ' - '${response.statusCode} ${response.reasonPhrase}'; + throw new HttpException('${response.statusCode} ${response.reasonPhrase}', + uri: uri); } List> splitContent = await response.toList(); int totalLength = 0; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index a629eafef..89b1855a9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.0.2 +version: 1.0.3-dev description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart index 0a2876726..c819a9074 100644 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -78,7 +78,7 @@ void validatePackagesDir(Packages resolver, Uri location) { if (location.scheme == "file") { expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } else { - expect(() => resolver.packages, throws); + expect(() => resolver.packages, throwsUnsupportedError); } } diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 897063f52..cbbca9a5d 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -41,7 +41,7 @@ void validatePackagesDir(Packages resolver, Uri location) { if (location.scheme == "file") { expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); } else { - expect(() => resolver.packages, throws); + expect(() => resolver.packages, throwsUnsupportedError); } } @@ -228,13 +228,16 @@ main() { generalTest("loadPackagesFile not found", {}, (Uri directory) async { Uri file = directory.resolve(".packages"); - expect(loadPackagesFile(file), throws); + expect( + loadPackagesFile(file), + throwsA(anyOf(new isInstanceOf(), + new isInstanceOf()))); }); generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, (Uri directory) async { Uri file = directory.resolve(".packages"); - expect(loadPackagesFile(file), throws); + expect(loadPackagesFile(file), throwsFormatException); }); generalTest("getPackagesDir", { diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 7a2fce7e2..fb3a6fab4 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -102,16 +102,18 @@ main() { for (int i = 0; i <= 255; i++) { if (map[i] == true) continue; var char = new String.fromCharCode(i); - expect(() => doParse("x${char}x:x", null), throws); + expect(() => doParse("x${char}x:x", null), + anyOf(throwsNoSuchMethodError, throwsFormatException)); } }); test("no escapes", () { - expect(() => doParse("x%41x:x", base), throws); + expect(() => doParse("x%41x:x", base), throwsFormatException); }); test("same name twice", () { - expect(() => doParse(singleRelativeSample * 2, base), throws); + expect( + () => doParse(singleRelativeSample * 2, base), throwsFormatException); }); for (String invalidSample in invalid) { From f0823a14d4f9cf4e9418dec716b2251087216de3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 12:06:22 -0700 Subject: [PATCH 083/281] Use travis tasks --- pkgs/package_config/.travis.yml | 18 +++++++++++++++--- pkgs/package_config/tool/travis.sh | 17 ----------------- 2 files changed, 15 insertions(+), 20 deletions(-) delete mode 100755 pkgs/package_config/tool/travis.sh diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index d7febddd1..24d56a3aa 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -1,5 +1,17 @@ language: dart -dart: dev -script: ./tool/travis.sh -dist: trusty sudo: false +dart: + - dev + - stable +dart_task: + - test + - dartfmt + - dartanalyzer: --fatal-warnings . + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/package_config/tool/travis.sh b/pkgs/package_config/tool/travis.sh deleted file mode 100755 index 6d8cfe375..000000000 --- a/pkgs/package_config/tool/travis.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2015, 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. - -# Fast fail the script on failures. -set -e - -# Verify that the libraries are error free. -dartanalyzer --fatal-warnings \ - lib/packages.dart \ - test/all.dart - -# Run the tests. -dart test/all.dart - From 25cf81831c5baf6c616c73bbca5325fbcb20cc4c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 12:06:38 -0700 Subject: [PATCH 084/281] Remove unneeded SDK constraint --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index c17c67498..a9ac0ec03 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.3 + +- Removed unneeded dependency constraint on SDK. + ## 1.0.2 - Update SDK constraint to be 2.0.0 dev friendly. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 89b1855a9..3d81eb2a4 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=1.11.0 <2.0.0-dev.infinity' + sdk: '>=1.11.0 <2.0.0' dependencies: charcode: ^1.1.0 From f37ecac7ba3642c72f55bc0d8da7283ddb2874f9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 12:06:44 -0700 Subject: [PATCH 085/281] dartfmt --- pkgs/package_config/lib/discovery.dart | 2 ++ pkgs/package_config/lib/discovery_analysis.dart | 2 ++ pkgs/package_config/test/discovery_test.dart | 2 ++ pkgs/package_config/test/parse_write_test.dart | 1 + 4 files changed, 7 insertions(+) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 2abf443fb..020d99a80 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -33,6 +33,7 @@ Future loadPackagesFile(Uri packagesFile, Map packageMap = pkgfile.parse(bytes, packagesFile); return new MapPackages(packageMap); } + if (packagesFile.scheme == "file") { File file = new File.fromUri(packagesFile); return parseBytes(await file.readAsBytes()); @@ -125,6 +126,7 @@ FileSystemEntity _findPackagesFile(String workingDirectory) { if (file.existsSync()) return file; return null; } + // Check for $cwd/.packages var packagesCfgFile = checkForConfigFile(dir); if (packagesCfgFile != null) return packagesCfgFile; diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index ce7e98a1a..67798e129 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -91,6 +91,7 @@ abstract class PackageContext { contexts = oldContexts; } } + findRoots(directory); // If the root is not itself context root, add a the wrapper context. if (contexts.length == 1 && contexts[0].directory == directory) { @@ -115,6 +116,7 @@ class _PackageContext implements PackageContext { recurse(child); } } + recurse(this); return result; } diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index cbbca9a5d..6a5bcdee9 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -169,6 +169,7 @@ main() { } throw "not found"; } + // A non-file: location with no .packages or packages/: // Assumes a packages dir exists, and resolves relative to that. Packages resolver; @@ -189,6 +190,7 @@ main() { Future> loader(Uri file) async { throw "not found"; } + // A non-file: location with no .packages or packages/: // Assumes a packages dir exists, and resolves relative to that. Packages resolver; diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart index 430218791..b963eb5b5 100644 --- a/pkgs/package_config/test/parse_write_test.dart +++ b/pkgs/package_config/test/parse_write_test.dart @@ -34,6 +34,7 @@ main() { }); }); } + var lowerDir = baseDir.resolve("path3/path4/"); var higherDir = baseDir.resolve("../"); var parallelDir = baseDir.resolve("../path3/"); From cae7ab5e1cb56408a2b7cbd66fbcd7da266dd27b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 12:28:07 -0700 Subject: [PATCH 086/281] Prepare for release --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 3d81eb2a4..bd2c6abaf 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.0.3-dev +version: 1.0.3 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From d531ea65453351093814b909891aaba2323b7563 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 22 Sep 2017 13:41:56 -0700 Subject: [PATCH 087/281] Declare support for async 2.0.0 (dart-lang/pool#11) --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index fbf12f2cb..d9db81c13 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.3 + +* Declare support for `async` 2.0.0. + ## 1.3.2 * Update to make the code work with strong-mode clean Zone API. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 3c65826e2..b9c5c8d9a 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,10 @@ name: pool -version: 1.3.2 +version: 1.3.3 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool dependencies: - async: "^1.4.0" + async: ">=1.4.0 <3.0.0" stack_trace: ">=0.9.2 <2.0.0" environment: sdk: ">=1.23.0 <2.0.0" From 1515f5e0da4141e288588cc99edb5013c14c1d84 Mon Sep 17 00:00:00 2001 From: keertip Date: Wed, 3 Jan 2018 13:22:26 -0800 Subject: [PATCH 088/281] Changes to eliminate future flattening --- pkgs/pool/lib/pool.dart | 2 +- pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 86f8363ce..ea3d2f016 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -122,7 +122,7 @@ class Pool { // synchronously in case the pool is closed immediately afterwards. Async // functions have an asynchronous gap between calling and running the body, // and [close] could be called during that gap. See #3. - return request().then>((resource) { + return request().then((resource) { return new Future.sync(callback).whenComplete(resource.release); }); } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index b9c5c8d9a..08f3b70f4 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.3 +version: 1.3.3-dev author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool From 59a18837dcfe9f293e83e785d34a1e43d19e057e Mon Sep 17 00:00:00 2001 From: keertip Date: Wed, 3 Jan 2018 14:47:44 -0800 Subject: [PATCH 089/281] prepare for release --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index d9db81c13..84b72c0f3 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.4 + +* Modify code to eliminate Future flattening. + ## 1.3.3 * Declare support for `async` 2.0.0. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 08f3b70f4..a5f043429 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.3-dev +version: 1.3.4 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool From cdd6d0bbe112ed98190684a1f555453200ac15b8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 14 Feb 2018 21:09:33 -0800 Subject: [PATCH 090/281] Remove tests on Dartium --- pkgs/pool/.travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index bf601a14f..a3c98ae1f 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -1,5 +1,5 @@ language: dart -sudo: false + dart: - dev - stable @@ -8,8 +8,6 @@ dart: dart_task: - test: --platform vm - test: --platform firefox - - test: --platform dartium - install_dartium: true - dartfmt - dartanalyzer From 0480257ce840ae9b9f64b5d6f4eb7484a8c690d3 Mon Sep 17 00:00:00 2001 From: pq Date: Sat, 10 Mar 2018 14:43:00 -0800 Subject: [PATCH 091/281] Update .gitignore to new `dart_tool` pub cache See: https://github.com/dart-lang/sdk/issues/32030 --- pkgs/package_config/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index a8b93ef38..4b1d87897 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -1,5 +1,5 @@ .packages -.pub +.dart_tool packages pubspec.lock doc/api/ From 589e7f23facd09b896b9b67bb63459dd8d79f705 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Sat, 10 Mar 2018 17:31:14 -0800 Subject: [PATCH 092/281] Update .gitignore --- pkgs/package_config/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index 4b1d87897..3b32e387c 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -1,5 +1,5 @@ .packages -.dart_tool +.dart_tool/ packages pubspec.lock doc/api/ From 7666429f5fa4adf5ca7cd9460b5ae25f256fcd2d Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Mon, 12 Mar 2018 09:30:31 -0700 Subject: [PATCH 093/281] Update .gitignore --- pkgs/package_config/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore index 3b32e387c..e41fc1916 100644 --- a/pkgs/package_config/.gitignore +++ b/pkgs/package_config/.gitignore @@ -1,4 +1,5 @@ .packages +.pub .dart_tool/ packages pubspec.lock From 2f368b1c5453f3ebf70009432b9f0fe4f0be2e7e Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 17 Apr 2018 09:51:16 +0200 Subject: [PATCH 094/281] Remove upper case constants (dart-lang/pool#13) Remove usage of upper-case constants. Updates SDK version to 2.0.0-dev.17.0 --- pkgs/pool/.travis.yml | 2 -- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/pubspec.yaml | 4 ++-- pkgs/pool/test/pool_test.dart | 40 +++++++++++++++++------------------ 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index a3c98ae1f..a9b5166a4 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -2,8 +2,6 @@ language: dart dart: - dev - - stable - - 1.23.0 dart_task: - test: --platform vm diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 84b72c0f3..46d142fca 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.5 + +- Updated SDK version to 2.0.0-dev.17.0 + ## 1.3.4 * Modify code to eliminate Future flattening. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index a5f043429..a628ec617 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.4 +version: 1.3.5 author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool @@ -7,7 +7,7 @@ dependencies: async: ">=1.4.0 <3.0.0" stack_trace: ">=0.9.2 <2.0.0" environment: - sdk: ">=1.23.0 <2.0.0" + sdk: ">=2.0.0-dev.17.0 <2.0.0" dev_dependencies: fake_async: ">=0.1.0 <0.2.0" test: ">=0.12.0 <0.13.0" diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 6feba75c3..d0e70170e 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -177,11 +177,11 @@ void main() { var resource = await pool.request(); var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(onReleaseCalled, isFalse); expect(pool.request(), completes); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); @@ -195,7 +195,7 @@ void main() { var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); @@ -208,11 +208,11 @@ void main() { var completer = new Completer(); resource.allowRelease(() => completer.future); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(requestComplete, isFalse); completer.complete(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(requestComplete, isTrue); }); @@ -233,7 +233,7 @@ void main() { onRelease1Called = true; return completer1.future; }); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(onRelease1Called, isTrue); var onRelease2Called = false; @@ -242,7 +242,7 @@ void main() { onRelease2Called = true; return completer2.future; }); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(onRelease2Called, isTrue); expect(request1Complete, isFalse); expect(request2Complete, isFalse); @@ -251,12 +251,12 @@ void main() { // was triggered by the second blocking request, it should complete the // first one to preserve ordering. completer2.complete(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isFalse); completer1.complete(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isTrue); }); @@ -286,7 +286,7 @@ void main() { var resource = await pool.request(); resource.release(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); }); group("close()", () { @@ -323,7 +323,7 @@ void main() { expect(pool.close(), completes); resource1.allowRelease(() => completer.future); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer.complete(); }); @@ -347,11 +347,11 @@ void main() { resource1Released = true; resource1.release(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); resource2Released = true; resource2.release(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); var resource3 = await resource3Future; resource3Released = true; @@ -372,10 +372,10 @@ void main() { }), completes); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); pool.close(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer.complete(); }); @@ -396,10 +396,10 @@ void main() { }), completes); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer1.complete(); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer2.complete(); }); @@ -414,10 +414,10 @@ void main() { }), completes); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); resource.allowRelease(() => completer.future); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer.complete(); }); @@ -431,7 +431,7 @@ void main() { expect(pool.done, throwsA("oh no!")); expect(pool.close(), throwsA("oh no!")); - await new Future.delayed(Duration.ZERO); + await new Future.delayed(Duration.zero); completer.completeError("oh no!"); }); }); From 239cd166346c69646d9f5f723fbe10d638db458c Mon Sep 17 00:00:00 2001 From: BC Ko Date: Thu, 24 May 2018 09:04:38 -0700 Subject: [PATCH 095/281] Update .gitignore to new `dart_tool` pub cache (dart-lang/pool#14) dart-lang/sdkdart-lang/pool#32030 --- pkgs/pool/.gitignore | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/pkgs/pool/.gitignore b/pkgs/pool/.gitignore index 7dbf0350d..e450c836d 100644 --- a/pkgs/pool/.gitignore +++ b/pkgs/pool/.gitignore @@ -1,15 +1,5 @@ # Don’t commit the following directories created by pub. -.buildlog -.pub/ -build/ -packages +.dart_tool/ .packages - -# Or the files created by dart2js. -*.dart.js -*.js_ -*.js.deps -*.js.map - -# Include when developing application packages. -pubspec.lock \ No newline at end of file +.pub/ +pubspec.lock From c15609e86734c64496bee259b55510bb214c3648 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 21 Jun 2018 10:50:26 -0700 Subject: [PATCH 096/281] core api use migrations --- pkgs/package_config/lib/packages_file.dart | 7 ++----- pkgs/package_config/lib/src/packages_impl.dart | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 0f1a6e635..85de1942d 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -159,12 +159,12 @@ Uri _relativize(Uri uri, Uri baseUri) { } } - baseUri = _normalizePath(baseUri); + baseUri = baseUri.normalizePath(); List base = baseUri.pathSegments.toList(); if (base.isNotEmpty) { base = new List.from(base)..removeLast(); } - uri = _normalizePath(uri); + uri = uri.normalizePath(); List target = uri.pathSegments.toList(); if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); int index = 0; @@ -186,6 +186,3 @@ Uri _relativize(Uri uri, Uri baseUri) { return uri; } } - -// TODO: inline to uri.normalizePath() when we move to 1.11 -Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index df89e4623..e89d94d22 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -23,7 +23,7 @@ class NoPackages implements Packages { packageUri, "packageUri", 'No package named "$packageName"'); } - Iterable get packages => new Iterable.generate(0); + Iterable get packages => new Iterable.empty(); Map asMap() => const {}; } @@ -34,7 +34,7 @@ class NoPackages implements Packages { /// member abstract class PackagesBase implements Packages { Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - packageUri = _normalizePath(packageUri); + packageUri = packageUri.normalizePath(); String packageName = checkValidPackageUri(packageUri); Uri packageBase = getBase(packageName); if (packageBase == null) { @@ -51,9 +51,6 @@ abstract class PackagesBase implements Packages { /// Returns `null` if no package exists with that name, and that can be /// determined. Uri getBase(String packageName); - - // TODO: inline to uri.normalizePath() when we move to 1.11 - static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri); } /// A [Packages] implementation based on an existing map. From 0ef6277d76402930b87be453b9b2bb7db2d6dd12 Mon Sep 17 00:00:00 2001 From: pq Date: Thu, 21 Jun 2018 14:01:44 -0700 Subject: [PATCH 097/281] dart2 --- pkgs/package_config/pubspec.yaml | 4 ++-- pkgs/package_config/test/discovery_test.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index bd2c6abaf..56d44f5ff 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -5,11 +5,11 @@ author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=1.11.0 <2.0.0' + sdk: '>=2.0.0-dev <2.0.0' dependencies: charcode: ^1.1.0 path: ^1.0.0 dev_dependencies: - test: ^0.12.0 + test: ^1.0.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 6a5bcdee9..2c60db389 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -289,7 +289,7 @@ void httpTest(String name, Map description, Future httpTest(Uri directory)) { if (path.startsWith('/')) path = path.substring(1); if (path.endsWith('/')) path = path.substring(0, path.length - 1); var parts = path.split('/'); - var fileOrDir = description; + dynamic fileOrDir = description; for (int i = 0; i < parts.length; i++) { fileOrDir = fileOrDir[parts[i]]; if (fileOrDir == null) { From 8785d418144ccd4efa2525375f91286c9acf0300 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 21 Jun 2018 14:05:58 -0700 Subject: [PATCH 098/281] Update .travis.yml --- pkgs/package_config/.travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index 24d56a3aa..655bf3dc1 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -2,7 +2,6 @@ language: dart sudo: false dart: - dev - - stable dart_task: - test - dartfmt From cbca72365e0805712a3742f2a5d906a43bf3cbc1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Jun 2018 09:38:36 -0700 Subject: [PATCH 099/281] misc(test): update dev dependencies, fix deprecations (dart-lang/pool#16) --- pkgs/pool/pubspec.yaml | 13 ++++++++----- pkgs/pool/test/pool_test.dart | 14 +++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index a628ec617..e10dadfdd 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,13 +1,16 @@ name: pool -version: 1.3.5 +version: 1.3.6-dev author: Dart Team description: A class for managing a finite pool of resources. homepage: https://github.com/dart-lang/pool + +environment: + sdk: ">=2.0.0-dev.17.0 <2.0.0" + dependencies: async: ">=1.4.0 <3.0.0" stack_trace: ">=0.9.2 <2.0.0" -environment: - sdk: ">=2.0.0-dev.17.0 <2.0.0" + dev_dependencies: - fake_async: ">=0.1.0 <0.2.0" - test: ">=0.12.0 <0.13.0" + fake_async: ^1.0.0 + test: ^1.0.0 diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index d0e70170e..cb0dd3009 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -55,7 +55,7 @@ void main() { test("can be called freely up to the limit", () { var pool = new Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync(() => new Completer().future)); + pool.withResource(expectAsync0(() => new Completer().future)); } }); @@ -63,7 +63,7 @@ void main() { new FakeAsync().run((async) { var pool = new Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync(() => new Completer().future)); + pool.withResource(expectAsync0(() => new Completer().future)); } pool.withResource(expectNoAsync()); @@ -75,7 +75,7 @@ void main() { new FakeAsync().run((async) { var pool = new Pool(50); for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync(() => new Completer().future)); + pool.withResource(expectAsync0(() => new Completer().future)); } var completer = new Completer(); @@ -100,7 +100,7 @@ void main() { // Regression test for #3. test("can be called immediately before close()", () async { var pool = new Pool(1); - pool.withResource(expectAsync(() {})); + pool.withResource(expectAsync0(() {})); await pool.close(); }); }); @@ -160,7 +160,7 @@ void main() { for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } - expect(pool.request(), throwsA(new isInstanceOf())); + expect(pool.request(), throwsA(new TypeMatcher())); async.elapse(new Duration(seconds: 6)); }); @@ -270,7 +270,7 @@ void main() { var innerZone = Zone.current; expect(innerZone, isNot(equals(outerZone))); - resource.allowRelease(expectAsync(() { + resource.allowRelease(expectAsync0(() { expect(Zone.current, equals(innerZone)); })); }); @@ -450,7 +450,7 @@ Function expectNoAsync() { /// /// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { - expect(future, new isInstanceOf()); + expect(future, new TypeMatcher()); var stack = new Trace.current(1); future.then((_) => registerException( From ae24ecbe7ee7ca69bd52af8f519c371a63631585 Mon Sep 17 00:00:00 2001 From: pq Date: Mon, 2 Jul 2018 16:27:38 -0700 Subject: [PATCH 100/281] Remove `strong`. --- pkgs/package_config/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 pkgs/package_config/analysis_options.yaml diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/package_config/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true From 5e14a449fa4fabf99960ad7f3df0aab91a0a5b23 Mon Sep 17 00:00:00 2001 From: pq Date: Sat, 14 Jul 2018 08:16:37 -0700 Subject: [PATCH 101/281] bump sdk constraint to 3.0.0 --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index a9ac0ec03..8c179c708 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.4 + +- Set max SDK version to <3.0.0. + ## 1.0.3 - Removed unneeded dependency constraint on SDK. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 56d44f5ff..c58468167 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,11 +1,11 @@ name: package_config -version: 1.0.3 +version: 1.0.4 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=2.0.0-dev <2.0.0' + sdk: '>=2.0.0-dev <3.0.0' dependencies: charcode: ^1.1.0 From cb0b2b16c733abc7e6c1d472da0f1ad18b9f326c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 18 Jul 2018 13:38:22 -0700 Subject: [PATCH 102/281] misc: fix usage of deprecated SDK constants (dart-lang/package_config#50) Also fixed usage of deprecated matcher classes --- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/lib/discovery.dart | 2 +- pkgs/package_config/pubspec.yaml | 4 ++-- pkgs/package_config/test/discovery_test.dart | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 8c179c708..e802d7deb 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.5 + +- Fix usage of SDK constants. + ## 1.0.4 - Set max SDK version to <3.0.0. diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index 020d99a80..57584b682 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -211,7 +211,7 @@ Future> _httpGet(Uri uri) async { HttpClient client = new HttpClient(); HttpClientRequest request = await client.getUrl(uri); HttpClientResponse response = await request.close(); - if (response.statusCode != HttpStatus.OK) { + if (response.statusCode != HttpStatus.ok) { throw new HttpException('${response.statusCode} ${response.reasonPhrase}', uri: uri); } diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index c58468167..4bad1cf52 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.0.4 +version: 1.0.5 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config @@ -12,4 +12,4 @@ dependencies: path: ^1.0.0 dev_dependencies: - test: ^1.0.0 + test: ^1.3.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 2c60db389..282427289 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -232,8 +232,8 @@ main() { Uri file = directory.resolve(".packages"); expect( loadPackagesFile(file), - throwsA(anyOf(new isInstanceOf(), - new isInstanceOf()))); + throwsA(anyOf(new TypeMatcher(), + new TypeMatcher()))); }); generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, @@ -280,7 +280,7 @@ void httpTest(String name, Map description, Future httpTest(Uri directory)) { var serverSub; var uri; setUp(() { - return HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) { + return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) { uri = new Uri( scheme: "http", host: "127.0.0.1", port: server.port, path: "/"); serverSub = server.listen((HttpRequest request) { From 4469273f26aa8584f271769853b5335ac62a7a21 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 20 Jul 2018 17:46:02 -0400 Subject: [PATCH 103/281] chore: set max SDK version to <3.0.0 (dart-lang/pool#17) --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/analysis_options.yaml | 2 -- pkgs/pool/pubspec.yaml | 11 ++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) delete mode 100644 pkgs/pool/analysis_options.yaml diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 46d142fca..98805184a 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.6 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 1.3.5 - Updated SDK version to 2.0.0-dev.17.0 diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/pool/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index e10dadfdd..84b97b236 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,15 +1,16 @@ name: pool -version: 1.3.6-dev -author: Dart Team +version: 1.3.6 + description: A class for managing a finite pool of resources. +author: Dart Team homepage: https://github.com/dart-lang/pool environment: - sdk: ">=2.0.0-dev.17.0 <2.0.0" + sdk: '>=2.0.0-dev.17.0 <3.0.0' dependencies: - async: ">=1.4.0 <3.0.0" - stack_trace: ">=0.9.2 <2.0.0" + async: '>=1.4.0 <3.0.0' + stack_trace: '>=0.9.2 <2.0.0' dev_dependencies: fake_async: ^1.0.0 From 182b21945130cdd4476a6affd8b70efcc1982837 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 28 Dec 2018 14:16:55 -0800 Subject: [PATCH 104/281] Enable and fix a number of lints (dart-lang/pool#19) --- pkgs/pool/analysis_options.yaml | 11 ++ pkgs/pool/lib/pool.dart | 45 ++++---- pkgs/pool/pubspec.yaml | 3 +- pkgs/pool/test/pool_test.dart | 187 ++++++++++++++++---------------- 4 files changed, 129 insertions(+), 117 deletions(-) create mode 100644 pkgs/pool/analysis_options.yaml diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml new file mode 100644 index 000000000..749f62afe --- /dev/null +++ b/pkgs/pool/analysis_options.yaml @@ -0,0 +1,11 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false +linter: + rules: + - await_only_futures + - implementation_imports + - prefer_typing_uninitialized_variables + - unnecessary_const + - unnecessary_new diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index ea3d2f016..416b14b73 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -21,20 +21,20 @@ class Pool { /// /// When an item is released, the next element of [_requestedResources] will /// be completed. - final _requestedResources = new Queue>(); + final _requestedResources = Queue>(); /// Callbacks that must be called before additional resources can be /// allocated. /// /// See [PoolResource.allowRelease]. - final _onReleaseCallbacks = new Queue(); + final _onReleaseCallbacks = Queue(); /// Completers that will be completed once `onRelease` callbacks are done /// running. /// /// These are kept in a queue to ensure that the earliest request completes /// first regardless of what order the `onRelease` callbacks complete in. - final _onReleaseCompleters = new Queue>(); + final _onReleaseCompleters = Queue>(); /// The maximum number of resources that may be allocated at once. final int _maxAllocatedResources; @@ -82,7 +82,7 @@ class Pool { if (timeout != null) { // Start the timer canceled since we only want to start counting down once // we've run out of available resources. - _timer = new RestartableTimer(timeout, _onTimeout)..cancel(); + _timer = RestartableTimer(timeout, _onTimeout)..cancel(); } } @@ -92,16 +92,16 @@ class Pool { /// until one of them is released. Future request() { if (isClosed) { - throw new StateError("request() may not be called on a closed Pool."); + throw StateError("request() may not be called on a closed Pool."); } if (_allocatedResources < _maxAllocatedResources) { _allocatedResources++; - return new Future.value(new PoolResource._(this)); + return Future.value(PoolResource._(this)); } else if (_onReleaseCallbacks.isNotEmpty) { return _runOnRelease(_onReleaseCallbacks.removeFirst()); } else { - var completer = new Completer(); + var completer = Completer(); _requestedResources.add(completer); _resetTimer(); return completer.future; @@ -114,8 +114,7 @@ class Pool { /// The return value of [callback] is piped to the returned Future. Future withResource(FutureOr callback()) { if (isClosed) { - throw new StateError( - "withResource() may not be called on a closed Pool."); + throw StateError("withResource() may not be called on a closed Pool."); } // We can't use async/await here because we need to start the request @@ -123,7 +122,7 @@ class Pool { // functions have an asynchronous gap between calling and running the body, // and [close] could be called during that gap. See #3. return request().then((resource) { - return new Future.sync(callback).whenComplete(resource.release); + return Future.sync(callback).whenComplete(resource.release); }); } @@ -143,9 +142,9 @@ class Pool { _resetTimer(); - _closeGroup = new FutureGroup(); + _closeGroup = FutureGroup(); for (var callback in _onReleaseCallbacks) { - _closeGroup.add(new Future.sync(callback)); + _closeGroup.add(Future.sync(callback)); } _allocatedResources -= _onReleaseCallbacks.length; @@ -154,7 +153,7 @@ class Pool { if (_allocatedResources == 0) _closeGroup.close(); return _closeGroup.future; }); - final _closeMemo = new AsyncMemoizer(); + final _closeMemo = AsyncMemoizer(); /// If there are any pending requests, this will fire the oldest one. void _onResourceReleased() { @@ -162,7 +161,7 @@ class Pool { if (_requestedResources.isNotEmpty) { var pending = _requestedResources.removeFirst(); - pending.complete(new PoolResource._(this)); + pending.complete(PoolResource._(this)); } else { _allocatedResources--; if (isClosed && _allocatedResources == 0) _closeGroup.close(); @@ -178,7 +177,7 @@ class Pool { var pending = _requestedResources.removeFirst(); pending.complete(_runOnRelease(onRelease)); } else if (isClosed) { - _closeGroup.add(new Future.sync(onRelease)); + _closeGroup.add(Future.sync(onRelease)); _allocatedResources--; if (_allocatedResources == 0) _closeGroup.close(); } else { @@ -194,13 +193,13 @@ class Pool { /// Futures returned by [_runOnRelease] always complete in the order they were /// created, even if earlier [onRelease] callbacks take longer to run. Future _runOnRelease(onRelease()) { - new Future.sync(onRelease).then((value) { - _onReleaseCompleters.removeFirst().complete(new PoolResource._(this)); - }).catchError((error, stackTrace) { + Future.sync(onRelease).then((value) { + _onReleaseCompleters.removeFirst().complete(PoolResource._(this)); + }).catchError((error, StackTrace stackTrace) { _onReleaseCompleters.removeFirst().completeError(error, stackTrace); }); - var completer = new Completer.sync(); + var completer = Completer.sync(); _onReleaseCompleters.add(completer); return completer.future; } @@ -221,11 +220,11 @@ class Pool { void _onTimeout() { for (var completer in _requestedResources) { completer.completeError( - new TimeoutException( + TimeoutException( "Pool deadlock: all resources have been " "allocated for too long.", _timeout), - new Chain.current()); + Chain.current()); } _requestedResources.clear(); _timer = null; @@ -248,7 +247,7 @@ class PoolResource { /// no longer allocated, and that a new [PoolResource] may be allocated. void release() { if (_released) { - throw new StateError("A PoolResource may only be released once."); + throw StateError("A PoolResource may only be released once."); } _released = true; _pool._onResourceReleased(); @@ -268,7 +267,7 @@ class PoolResource { /// may be complete, but it could still emit asynchronous errors. void allowRelease(onRelease()) { if (_released) { - throw new StateError("A PoolResource may only be released once."); + throw StateError("A PoolResource may only be released once."); } _released = true; _pool._onResourceReleaseAllowed(onRelease); diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 84b97b236..a709842c9 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.6 +version: 1.3.7-dev description: A class for managing a finite pool of resources. author: Dart Team @@ -14,4 +14,5 @@ dependencies: dev_dependencies: fake_async: ^1.0.0 + pedantic: ^1.4.0 test: ^1.0.0 diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index cb0dd3009..a156c521e 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:fake_async/fake_async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; @@ -12,27 +13,27 @@ import 'package:test/test.dart'; void main() { group("request()", () { test("resources can be requested freely up to the limit", () { - var pool = new Pool(50); + var pool = Pool(50); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } }); test("resources block past the limit", () { - new FakeAsync().run((async) { - var pool = new Pool(50); + FakeAsync().run((async) { + var pool = Pool(50); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } expect(pool.request(), doesNotComplete); - async.elapse(new Duration(seconds: 1)); + async.elapse(Duration(seconds: 1)); }); }); test("a blocked resource is allocated when another is released", () { - new FakeAsync().run((async) { - var pool = new Pool(50); + FakeAsync().run((async) { + var pool = Pool(50); for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } @@ -41,85 +42,85 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - new Future.delayed(new Duration(microseconds: 1)).then((_) { + Future.delayed(Duration(microseconds: 1)).then((_) { lastAllocatedResource.release(); }); }); - async.elapse(new Duration(seconds: 1)); + async.elapse(Duration(seconds: 1)); }); }); }); group("withResource()", () { test("can be called freely up to the limit", () { - var pool = new Pool(50); + var pool = Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync0(() => new Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } }); test("blocks the callback past the limit", () { - new FakeAsync().run((async) { - var pool = new Pool(50); + FakeAsync().run((async) { + var pool = Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync0(() => new Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } pool.withResource(expectNoAsync()); - async.elapse(new Duration(seconds: 1)); + async.elapse(Duration(seconds: 1)); }); }); test("a blocked resource is allocated when another is released", () { - new FakeAsync().run((async) { - var pool = new Pool(50); + FakeAsync().run((async) { + var pool = Pool(50); for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync0(() => new Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } - var completer = new Completer(); + var completer = Completer(); pool.withResource(() => completer.future); var blockedResourceAllocated = false; pool.withResource(() { blockedResourceAllocated = true; }); - new Future.delayed(new Duration(microseconds: 1)).then((_) { + Future.delayed(Duration(microseconds: 1)).then((_) { expect(blockedResourceAllocated, isFalse); completer.complete(); - return new Future.delayed(new Duration(microseconds: 1)); + return Future.delayed(Duration(microseconds: 1)); }).then((_) { expect(blockedResourceAllocated, isTrue); }); - async.elapse(new Duration(seconds: 1)); + async.elapse(Duration(seconds: 1)); }); }); // Regression test for #3. test("can be called immediately before close()", () async { - var pool = new Pool(1); - pool.withResource(expectAsync0(() {})); + var pool = Pool(1); + unawaited(pool.withResource(expectAsync0(() {}))); await pool.close(); }); }); group("with a timeout", () { test("doesn't time out if there are no pending requests", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); + FakeAsync().run((async) { + var pool = Pool(50, timeout: Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } - async.elapse(new Duration(seconds: 6)); + async.elapse(Duration(seconds: 6)); }); }); test("resets the timer if a resource is returned", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); + FakeAsync().run((async) { + var pool = Pool(50, timeout: Duration(seconds: 5)); for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } @@ -128,48 +129,48 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - new Future.delayed(new Duration(seconds: 3)).then((_) { + Future.delayed(Duration(seconds: 3)).then((_) { lastAllocatedResource.release(); expect(pool.request(), doesNotComplete); }); }); - async.elapse(new Duration(seconds: 6)); + async.elapse(Duration(seconds: 6)); }); }); test("resets the timer if a resource is requested", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); + FakeAsync().run((async) { + var pool = Pool(50, timeout: Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } expect(pool.request(), doesNotComplete); - new Future.delayed(new Duration(seconds: 3)).then((_) { + Future.delayed(Duration(seconds: 3)).then((_) { expect(pool.request(), doesNotComplete); }); - async.elapse(new Duration(seconds: 6)); + async.elapse(Duration(seconds: 6)); }); }); test("times out if nothing happens", () { - new FakeAsync().run((async) { - var pool = new Pool(50, timeout: new Duration(seconds: 5)); + FakeAsync().run((async) { + var pool = Pool(50, timeout: Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } - expect(pool.request(), throwsA(new TypeMatcher())); + expect(pool.request(), throwsA(TypeMatcher())); - async.elapse(new Duration(seconds: 6)); + async.elapse(Duration(seconds: 6)); }); }); }); group("allowRelease()", () { test("runs the callback once the resource limit is exceeded", () async { - var pool = new Pool(50); + var pool = Pool(50); for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } @@ -177,17 +178,17 @@ void main() { var resource = await pool.request(); var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isFalse); expect(pool.request(), completes); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); test("runs the callback immediately if there are blocked requests", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); // This will be blocked until [resource.allowRelease] is called. @@ -195,54 +196,54 @@ void main() { var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); test("blocks the request until the callback completes", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); var requestComplete = false; - pool.request().then((_) => requestComplete = true); + unawaited(pool.request().then((_) => requestComplete = true)); - var completer = new Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(requestComplete, isFalse); completer.complete(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(requestComplete, isTrue); }); test("completes requests in request order regardless of callback order", () async { - var pool = new Pool(2); + var pool = Pool(2); var resource1 = await pool.request(); var resource2 = await pool.request(); var request1Complete = false; - pool.request().then((_) => request1Complete = true); + unawaited(pool.request().then((_) => request1Complete = true)); var request2Complete = false; - pool.request().then((_) => request2Complete = true); + unawaited(pool.request().then((_) => request2Complete = true)); var onRelease1Called = false; - var completer1 = new Completer(); + var completer1 = Completer(); resource1.allowRelease(() { onRelease1Called = true; return completer1.future; }); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onRelease1Called, isTrue); var onRelease2Called = false; - var completer2 = new Completer(); + var completer2 = Completer(); resource2.allowRelease(() { onRelease2Called = true; return completer2.future; }); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onRelease2Called, isTrue); expect(request1Complete, isFalse); expect(request2Complete, isFalse); @@ -251,18 +252,18 @@ void main() { // was triggered by the second blocking request, it should complete the // first one to preserve ordering. completer2.complete(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isFalse); completer1.complete(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isTrue); }); test("runs onRequest in the zone it was created", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); var outerZone = Zone.current; @@ -275,29 +276,29 @@ void main() { })); }); - pool.request(); + await pool.request(); }); }); test("done doesn't complete without close", () async { - var pool = new Pool(1); - pool.done.then(expectAsync1((_) {}, count: 0)); + var pool = Pool(1); + unawaited(pool.done.then(expectAsync1((_) {}, count: 0))); var resource = await pool.request(); resource.release(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); }); group("close()", () { test("disallows request() and withResource()", () { - var pool = new Pool(1)..close(); + var pool = Pool(1)..close(); expect(pool.request, throwsStateError); expect(() => pool.withResource(() {}), throwsStateError); }); test("pending requests are fulfilled", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource1 = await pool.request(); expect( pool.request().then((resource2) { @@ -310,10 +311,10 @@ void main() { }); test("pending requests are fulfilled with allowRelease", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource1 = await pool.request(); - var completer = new Completer(); + var completer = Completer(); expect( pool.request().then((resource2) { expect(completer.isCompleted, isTrue); @@ -323,13 +324,13 @@ void main() { expect(pool.close(), completes); resource1.allowRelease(() => completer.future); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); test("doesn't complete until all resources are released", () async { - var pool = new Pool(2); + var pool = Pool(2); var resource1 = await pool.request(); var resource2 = await pool.request(); var resource3Future = pool.request(); @@ -347,11 +348,11 @@ void main() { resource1Released = true; resource1.release(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); resource2Released = true; resource2.release(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); var resource3 = await resource3Future; resource3Released = true; @@ -359,12 +360,12 @@ void main() { }); test("active onReleases complete as usual", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); // Set up an onRelease callback whose completion is controlled by // [completer]. - var completer = new Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); expect( pool.request().then((_) { @@ -372,21 +373,21 @@ void main() { }), completes); - await new Future.delayed(Duration.zero); - pool.close(); + await Future.delayed(Duration.zero); + unawaited(pool.close()); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); test("inactive onReleases fire", () async { - var pool = new Pool(2); + var pool = Pool(2); var resource1 = await pool.request(); var resource2 = await pool.request(); - var completer1 = new Completer(); + var completer1 = Completer(); resource1.allowRelease(() => completer1.future); - var completer2 = new Completer(); + var completer2 = Completer(); resource2.allowRelease(() => completer2.future); expect( @@ -396,42 +397,42 @@ void main() { }), completes); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer1.complete(); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer2.complete(); }); test("new allowReleases fire immediately", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); - var completer = new Completer(); + var completer = Completer(); expect( pool.close().then((_) { expect(completer.isCompleted, isTrue); }), completes); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); resource.allowRelease(() => completer.future); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); test("an onRelease error is piped to the return value", () async { - var pool = new Pool(1); + var pool = Pool(1); var resource = await pool.request(); - var completer = new Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); expect(pool.done, throwsA("oh no!")); expect(pool.close(), throwsA("oh no!")); - await new Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.completeError("oh no!"); }); }); @@ -440,20 +441,20 @@ void main() { /// Returns a function that will cause the test to fail if it's called. /// /// This should only be called within a [FakeAsync.run] zone. -Function expectNoAsync() { - var stack = new Trace.current(1); +void Function() expectNoAsync() { + var stack = Trace.current(1); return () => registerException( - new TestFailure("Expected function not to be called."), stack); + TestFailure("Expected function not to be called."), stack); } /// A matcher for Futures that asserts that they don't complete. /// /// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { - expect(future, new TypeMatcher()); + expect(future, TypeMatcher()); - var stack = new Trace.current(1); + var stack = Trace.current(1); future.then((_) => registerException( - new TestFailure("Expected future not to complete."), stack)); + TestFailure("Expected future not to complete."), stack)); return true; }); From 78e15a61f29cd9e25c58c934e132b6e114158501 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 28 Dec 2018 15:24:33 -0800 Subject: [PATCH 105/281] Update Pool.withResource to use async/await (dart-lang/pool#21) Dart 2+ implements sync-async, so the root issue is no longer applicable A regression test exists to validate the behavior --- pkgs/pool/lib/pool.dart | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 416b14b73..a4a7d93ec 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -112,18 +112,17 @@ class Pool { /// Future. /// /// The return value of [callback] is piped to the returned Future. - Future withResource(FutureOr callback()) { + Future withResource(FutureOr callback()) async { if (isClosed) { throw StateError("withResource() may not be called on a closed Pool."); } - // We can't use async/await here because we need to start the request - // synchronously in case the pool is closed immediately afterwards. Async - // functions have an asynchronous gap between calling and running the body, - // and [close] could be called during that gap. See #3. - return request().then((resource) { - return Future.sync(callback).whenComplete(resource.release); - }); + var resource = await request(); + try { + return await callback(); + } finally { + resource.release(); + } } /// Closes the pool so that no more resources are requested. From 85c565435aa9f42f10d102a08efb982a94d4d8c9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 8 Jan 2019 00:25:08 +0200 Subject: [PATCH 106/281] Fix: Throw ArgumentError if poolSize <= 0 (dart-lang/pool#24) Fixes dart-lang/pool#20 --- pkgs/pool/lib/pool.dart | 4 ++++ pkgs/pool/test/pool_test.dart | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index a4a7d93ec..40a258054 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -79,6 +79,10 @@ class Pool { /// all pending [request] futures will throw a [TimeoutException]. This is /// intended to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout { + if (_maxAllocatedResources <= 0) { + throw ArgumentError('pool limit should be > 0'); + } + if (timeout != null) { // Start the timer canceled since we only want to start counting down once // we've run out of available resources. diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index a156c521e..66624cf24 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -436,6 +436,11 @@ void main() { completer.completeError("oh no!"); }); }); + + test("throw error when pool limit <= 0", () { + expect(() => Pool(-1), throwsArgumentError); + expect(() => Pool(0), throwsArgumentError); + }); } /// Returns a function that will cause the test to fail if it's called. From 0424d6e87c46c7c0836fb80d12eb3f7910e765aa Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 8 Jan 2019 00:48:29 +0200 Subject: [PATCH 107/281] Update CHANGELOG (dart-lang/pool#25) --- pkgs/pool/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 98805184a..10727a56d 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## x.x.x + +* Throw ArgumentError if poolSize <= 0 + ## 1.3.6 * Set max SDK version to `<3.0.0`, and adjust other dependencies. From e8cfb7f3e7163f7cc73c6704e9fb8038d084522d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 7 Jan 2019 14:30:19 -0800 Subject: [PATCH 108/281] Throw a more descriptive ArgumentError for invalid maxAllocatedResources --- pkgs/pool/lib/pool.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 40a258054..6994c7606 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -80,7 +80,8 @@ class Pool { /// intended to avoid deadlocks. Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout { if (_maxAllocatedResources <= 0) { - throw ArgumentError('pool limit should be > 0'); + throw ArgumentError.value(_maxAllocatedResources, 'maxAllocatedResources', + 'Must be greater than zero.'); } if (timeout != null) { From b0fce41b2bc78944ab541e16466bdc05a6b71a01 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 7 Jan 2019 14:33:05 -0800 Subject: [PATCH 109/281] enable and fix a number of lints --- pkgs/pool/analysis_options.yaml | 72 +++++++++++++++++++++++++++++++++ pkgs/pool/lib/pool.dart | 10 ++--- pkgs/pool/test/pool_test.dart | 4 +- 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 749f62afe..f8eebb47a 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -4,8 +4,80 @@ analyzer: implicit-casts: false linter: rules: + - always_declare_return_types + - annotate_overrides + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_future + - avoid_shadowing_type_parameters + - avoid_types_as_parameter_names + - avoid_unused_constructor_parameters - await_only_futures + - camel_case_types + - cancel_subscriptions + - comment_references + - constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - hash_and_equals - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - library_names + - library_prefixes + - list_remove_unrelated_type + - literal_only_boolean_expressions + - no_adjacent_strings_in_list + - no_duplicate_case_values + - non_constant_identifier_names + - null_closures + - omit_local_variable_types + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + #- prefer_final_locals + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + #- prefer_single_quotes - prefer_typing_uninitialized_variables + - recursive_getters + - slash_for_doc_comments + - super_goes_last + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unawaited_futures + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps - unnecessary_const + - unnecessary_getters_setters + - unnecessary_lambdas - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_this + - unrelated_type_equality_checks + - use_function_type_syntax_for_parameters + - use_rethrow_when_possible + - valid_regexps diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 6994c7606..a97ec75c2 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -117,7 +117,7 @@ class Pool { /// Future. /// /// The return value of [callback] is piped to the returned Future. - Future withResource(FutureOr callback()) async { + Future withResource(FutureOr Function() callback) async { if (isClosed) { throw StateError("withResource() may not be called on a closed Pool."); } @@ -174,7 +174,7 @@ class Pool { /// If there are any pending requests, this will fire the oldest one after /// running [onRelease]. - void _onResourceReleaseAllowed(onRelease()) { + void _onResourceReleaseAllowed(Function() onRelease) { _resetTimer(); if (_requestedResources.isNotEmpty) { @@ -196,7 +196,7 @@ class Pool { /// /// Futures returned by [_runOnRelease] always complete in the order they were /// created, even if earlier [onRelease] callbacks take longer to run. - Future _runOnRelease(onRelease()) { + Future _runOnRelease(Function() onRelease) { Future.sync(onRelease).then((value) { _onReleaseCompleters.removeFirst().complete(PoolResource._(this)); }).catchError((error, StackTrace stackTrace) { @@ -242,7 +242,7 @@ class Pool { class PoolResource { final Pool _pool; - /// Whether [this] has been released yet. + /// Whether `this` has been released yet. bool _released = false; PoolResource._(this._pool); @@ -269,7 +269,7 @@ class PoolResource { /// This is useful when a resource's main function is complete, but it may /// produce additional information later on. For example, an isolate's task /// may be complete, but it could still emit asynchronous errors. - void allowRelease(onRelease()) { + void allowRelease(Function() onRelease) { if (_released) { throw StateError("A PoolResource may only be released once."); } diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 66624cf24..6c9d0a56b 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -161,7 +161,7 @@ void main() { for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } - expect(pool.request(), throwsA(TypeMatcher())); + expect(pool.request(), throwsA(const TypeMatcher())); async.elapse(Duration(seconds: 6)); }); @@ -456,7 +456,7 @@ void Function() expectNoAsync() { /// /// This should only be called within a [FakeAsync.run] zone. Matcher get doesNotComplete => predicate((future) { - expect(future, TypeMatcher()); + expect(future, const TypeMatcher()); var stack = Trace.current(1); future.then((_) => registerException( From 2e815524c07349b076fc4f29bb6898dbd07d2647 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Jan 2019 16:09:49 -0800 Subject: [PATCH 110/281] add forEach to Pool (dart-lang/pool#23) Fixes https://github.com/dart-lang/pool/issues/22 --- pkgs/pool/.travis.yml | 2 +- pkgs/pool/CHANGELOG.md | 5 +- pkgs/pool/lib/pool.dart | 97 +++++++++++ pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 316 ++++++++++++++++++++++++++++++++-- 5 files changed, 402 insertions(+), 20 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index a9b5166a4..07e132f33 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -7,7 +7,7 @@ dart_task: - test: --platform vm - test: --platform firefox - dartfmt - - dartanalyzer + - dartanalyzer: --fatal-infos --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 10727a56d..0c3d314a6 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,4 +1,7 @@ -## x.x.x +## 1.4.0 + +* Add `forEach` to `Pool` to support efficient async processing of an + `Iterable`. * Throw ArgumentError if poolSize <= 0 diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index a97ec75c2..779300e2b 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -130,6 +130,103 @@ class Pool { } } + /// Returns a [Stream] containing the result of [action] applied to each + /// element of [elements]. + /// + /// While [action] is invoked on each element of [elements] in order, + /// it's possible the return [Stream] may have items out-of-order – especially + /// if the completion time of [action] varies. + /// + /// If [action] throws an error the source item along with the error object + /// and [StackTrace] are passed to [onError], if it is provided. If [onError] + /// returns `true`, the error is added to the returned [Stream], otherwise + /// it is ignored. + /// + /// Errors thrown from iterating [elements] will not be passed to + /// [onError]. They will always be added to the returned stream as an error. + /// + /// Note: all of the resources of the this [Pool] will be used when the + /// returned [Stream] is listened to until it is completed or canceled. + /// + /// Note: if this [Pool] is closed before the returned [Stream] is listened + /// to, a [StateError] is thrown. + Stream forEach( + Iterable elements, FutureOr Function(S source) action, + {bool Function(S item, Object error, StackTrace stack) onError}) { + onError ??= (item, e, s) => true; + + var cancelPending = false; + + Completer resumeCompleter; + StreamController controller; + + Iterator iterator; + + Future run(int i) async { + while (iterator.moveNext()) { + // caching `current` is necessary because there are async breaks + // in this code and `iterator` is shared across many workers + final current = iterator.current; + + _resetTimer(); + + await resumeCompleter?.future; + + if (cancelPending) { + break; + } + + T value; + try { + value = await action(current); + } catch (e, stack) { + if (onError(current, e, stack)) { + controller.addError(e, stack); + } + continue; + } + controller.add(value); + } + } + + Future doneFuture; + + void onListen() { + assert(iterator == null); + iterator = elements.iterator; + + assert(doneFuture == null); + doneFuture = Future.wait( + Iterable.generate(_maxAllocatedResources) + .map((i) => withResource(() => run(i))), + eagerError: true) + .catchError(controller.addError); + + doneFuture.whenComplete(controller.close); + } + + controller = StreamController( + sync: true, + onListen: onListen, + onCancel: () async { + assert(!cancelPending); + cancelPending = true; + await doneFuture; + }, + onPause: () { + assert(resumeCompleter == null); + resumeCompleter = Completer(); + }, + onResume: () { + assert(resumeCompleter != null); + resumeCompleter.complete(); + resumeCompleter = null; + }, + ); + + return controller.stream; + } + /// Closes the pool so that no more resources are requested. /// /// Existing resource requests remain unchanged. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index a709842c9..095c38564 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.3.7-dev +version: 1.4.0-dev description: A class for managing a finite pool of resources. author: Dart Team diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 6c9d0a56b..d4d778992 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -27,7 +27,7 @@ void main() { } expect(pool.request(), doesNotComplete); - async.elapse(Duration(seconds: 1)); + async.elapse(const Duration(seconds: 1)); }); }); @@ -42,12 +42,12 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - Future.delayed(Duration(microseconds: 1)).then((_) { + Future.delayed(const Duration(microseconds: 1)).then((_) { lastAllocatedResource.release(); }); }); - async.elapse(Duration(seconds: 1)); + async.elapse(const Duration(seconds: 1)); }); }); }); @@ -68,7 +68,7 @@ void main() { } pool.withResource(expectNoAsync()); - async.elapse(Duration(seconds: 1)); + async.elapse(const Duration(seconds: 1)); }); }); @@ -86,15 +86,15 @@ void main() { blockedResourceAllocated = true; }); - Future.delayed(Duration(microseconds: 1)).then((_) { + Future.delayed(const Duration(microseconds: 1)).then((_) { expect(blockedResourceAllocated, isFalse); completer.complete(); - return Future.delayed(Duration(microseconds: 1)); + return Future.delayed(const Duration(microseconds: 1)); }).then((_) { expect(blockedResourceAllocated, isTrue); }); - async.elapse(Duration(seconds: 1)); + async.elapse(const Duration(seconds: 1)); }); }); @@ -109,18 +109,18 @@ void main() { group("with a timeout", () { test("doesn't time out if there are no pending requests", () { FakeAsync().run((async) { - var pool = Pool(50, timeout: Duration(seconds: 5)); + var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } - async.elapse(Duration(seconds: 6)); + async.elapse(const Duration(seconds: 6)); }); }); test("resets the timer if a resource is returned", () { FakeAsync().run((async) { - var pool = Pool(50, timeout: Duration(seconds: 5)); + var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 49; i++) { expect(pool.request(), completes); } @@ -129,41 +129,41 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - Future.delayed(Duration(seconds: 3)).then((_) { + Future.delayed(const Duration(seconds: 3)).then((_) { lastAllocatedResource.release(); expect(pool.request(), doesNotComplete); }); }); - async.elapse(Duration(seconds: 6)); + async.elapse(const Duration(seconds: 6)); }); }); test("resets the timer if a resource is requested", () { FakeAsync().run((async) { - var pool = Pool(50, timeout: Duration(seconds: 5)); + var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } expect(pool.request(), doesNotComplete); - Future.delayed(Duration(seconds: 3)).then((_) { + Future.delayed(const Duration(seconds: 3)).then((_) { expect(pool.request(), doesNotComplete); }); - async.elapse(Duration(seconds: 6)); + async.elapse(const Duration(seconds: 6)); }); }); test("times out if nothing happens", () { FakeAsync().run((async) { - var pool = Pool(50, timeout: Duration(seconds: 5)); + var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } expect(pool.request(), throwsA(const TypeMatcher())); - async.elapse(Duration(seconds: 6)); + async.elapse(const Duration(seconds: 6)); }); }); }); @@ -437,6 +437,288 @@ void main() { }); }); + group('forEach', () { + Pool pool; + + tearDown(() async { + await pool.close(); + }); + + const delayedToStringDuration = Duration(milliseconds: 10); + + Future delayedToString(int i) => + Future.delayed(delayedToStringDuration, () => i.toString()); + + for (var itemCount in [0, 5]) { + for (var poolSize in [1, 5, 6]) { + test('poolSize: $poolSize, itemCount: $itemCount', () async { + pool = Pool(poolSize); + + var finishedItems = 0; + + await for (var item in pool.forEach( + Iterable.generate(itemCount, (i) { + expect(i, lessThanOrEqualTo(finishedItems + poolSize), + reason: 'the iterator should be called lazily'); + return i; + }), + delayedToString)) { + expect(int.parse(item), lessThan(itemCount)); + finishedItems++; + } + + expect(finishedItems, itemCount); + }); + } + } + + test('pool closed before listen', () async { + pool = Pool(2); + + var stream = pool.forEach(Iterable.generate(5), delayedToString); + + await pool.close(); + + expect(stream.toList(), throwsStateError); + }); + + test('completes even if the pool is partially used', () async { + pool = Pool(2); + + var resource = await pool.request(); + + var stream = pool.forEach([], delayedToString); + + expect(await stream.length, 0); + + resource.release(); + }); + + test('stream paused longer than timeout', () async { + pool = Pool(2, timeout: delayedToStringDuration); + + var resource = await pool.request(); + + var stream = pool.forEach( + Iterable.generate(100, (i) { + expect(i, lessThan(20), + reason: 'The timeout should happen ' + 'before the entire iterable is iterated.'); + return i; + }), (i) async { + await Future.delayed(Duration(milliseconds: i)); + return i; + }); + + await expectLater( + stream.toList, + throwsA(const TypeMatcher().having( + (te) => te.message, + 'message', + contains('Pool deadlock: ' + 'all resources have been allocated for too long.')))); + + resource.release(); + }); + + group('timing and timeout', () { + for (var poolSize in [2, 8, 64]) { + for (var otherTaskCount + in [0, 1, 7, 63].where((otc) => otc < poolSize)) { + test('poolSize: $poolSize, otherTaskCount: $otherTaskCount', + () async { + final itemCount = 128; + pool = Pool(poolSize, timeout: const Duration(milliseconds: 20)); + + var otherTasks = await Future.wait( + Iterable.generate(otherTaskCount) + .map((i) => pool.request())); + + try { + var finishedItems = 0; + + var watch = Stopwatch()..start(); + + await for (var item in pool.forEach( + Iterable.generate(itemCount, (i) { + expect(i, lessThanOrEqualTo(finishedItems + poolSize), + reason: 'the iterator should be called lazily'); + return i; + }), + delayedToString)) { + expect(int.parse(item), lessThan(itemCount)); + finishedItems++; + } + + expect(finishedItems, itemCount); + + final expectedElapsed = + delayedToStringDuration.inMicroseconds * 3; + + expect((watch.elapsed ~/ itemCount).inMicroseconds, + lessThan(expectedElapsed / (poolSize - otherTaskCount)), + reason: 'Average time per task should be ' + 'proportionate to the available pool resources.'); + } finally { + for (var task in otherTasks) { + task.release(); + } + } + }); + } + } + }, testOn: 'vm'); + + test('partial iteration', () async { + pool = Pool(5); + var stream = pool.forEach(Iterable.generate(100), delayedToString); + expect(await stream.take(10).toList(), hasLength(10)); + }); + + test('pool close during data with waiting to be done', () async { + pool = Pool(5); + + var stream = pool.forEach(Iterable.generate(100), delayedToString); + + var dataCount = 0; + var subscription = stream.listen((data) { + dataCount++; + pool.close(); + }); + + await subscription.asFuture(); + expect(dataCount, 100); + await subscription.cancel(); + }); + + test('pause and resume ', () async { + var generatedCount = 0; + var dataCount = 0; + final poolSize = 5; + + pool = Pool(poolSize); + + var stream = pool.forEach( + Iterable.generate(40, (i) { + expect(generatedCount, lessThanOrEqualTo(dataCount + 2 * poolSize), + reason: 'The iterator should not be called ' + 'much faster than the data is consumed.'); + generatedCount++; + return i; + }), + delayedToString); + + // ignore: cancel_subscriptions + StreamSubscription subscription; + + subscription = stream.listen( + (data) { + dataCount++; + + if (int.parse(data) % 3 == 1) { + subscription.pause(Future(() async { + await Future.delayed(const Duration(milliseconds: 100)); + })); + } + }, + onError: registerException, + onDone: expectAsync0(() { + expect(dataCount, 40); + }), + ); + }); + + group('cancel', () { + final dataSize = 32; + for (var i = 1; i < 5; i++) { + test('with pool size $i', () async { + pool = Pool(i); + + var stream = + pool.forEach(Iterable.generate(dataSize), delayedToString); + + var cancelCompleter = Completer(); + + StreamSubscription subscription; + + var eventCount = 0; + subscription = stream.listen((data) { + eventCount++; + if (int.parse(data) == dataSize ~/ 2) { + cancelCompleter.complete(); + } + }, onError: registerException); + + await cancelCompleter.future; + + await subscription.cancel(); + + expect(eventCount, 1 + dataSize ~/ 2); + }); + } + }); + + group('errors', () { + Future errorInIterator( + {bool Function(int item, Object error, StackTrace stack) + onError}) async { + pool = Pool(20); + + var listFuture = pool + .forEach( + Iterable.generate(100, (i) { + if (i == 50) { + throw StateError('error while generating item in iterator'); + } + + return i; + }), + delayedToString, + onError: onError) + .toList(); + + await expectLater(() async => listFuture, throwsStateError); + } + + test('iteration, no onError', () async { + await errorInIterator(); + }); + test('iteration, with onError', () async { + await errorInIterator(onError: (i, e, s) => false); + }); + + test('error in action, no onError', () async { + pool = Pool(20); + + var listFuture = pool.forEach(Iterable.generate(100), (i) async { + await Future.delayed(const Duration(milliseconds: 10)); + if (i == 10) { + throw UnsupportedError('10 is not supported'); + } + return i.toString(); + }).toList(); + + await expectLater(() async => listFuture, throwsUnsupportedError); + }); + + test('error in action, no onError', () async { + pool = Pool(20); + + var list = await pool.forEach(Iterable.generate(100), (i) async { + await Future.delayed(const Duration(milliseconds: 10)); + if (i % 10 == 0) { + throw UnsupportedError('Multiples of 10 not supported'); + } + return i.toString(); + }, + onError: (item, error, stack) => + error is! UnsupportedError).toList(); + + expect(list, hasLength(90)); + }); + }); + }); + test("throw error when pool limit <= 0", () { expect(() => Pool(-1), throwsArgumentError); expect(() => Pool(0), throwsArgumentError); From eb689f6e131c85e4a09f90839ae07c0788e03ab1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Jan 2019 17:06:06 -0800 Subject: [PATCH 111/281] Prepare for v1.4.0 release (dart-lang/pool#27) --- pkgs/pool/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 095c38564..248d9199b 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,12 +1,12 @@ name: pool -version: 1.4.0-dev +version: 1.4.0 description: A class for managing a finite pool of resources. author: Dart Team homepage: https://github.com/dart-lang/pool environment: - sdk: '>=2.0.0-dev.17.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: async: '>=1.4.0 <3.0.0' From f29cfd07622c3374e7adceb8756eea2cb6590dd3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Jan 2019 17:10:24 -0800 Subject: [PATCH 112/281] update description --- pkgs/pool/pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 248d9199b..c9e78cb77 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,7 +1,9 @@ name: pool version: 1.4.0 -description: A class for managing a finite pool of resources. +description: >- + Manage a finite pool of resources. + Useful for controlling concurrent I/O requests on the file system or network. author: Dart Team homepage: https://github.com/dart-lang/pool From ad6eef43088eb330ef3b327719683fad6459f757 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Jan 2019 17:10:48 -0800 Subject: [PATCH 113/281] update description --- pkgs/pool/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index c9e78cb77..35fb62dee 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.4.0 description: >- Manage a finite pool of resources. - Useful for controlling concurrent I/O requests on the file system or network. + Useful for controlling concurrent file system or network requests. author: Dart Team homepage: https://github.com/dart-lang/pool From a526c2d57bbb60fbdbaa02c97fb6fc369dc989d2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 10 Jan 2019 15:45:57 -0800 Subject: [PATCH 114/281] Add basic forEach benchmark --- pkgs/pool/benchmark/for_each_benchmark.dart | 51 +++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 pkgs/pool/benchmark/for_each_benchmark.dart diff --git a/pkgs/pool/benchmark/for_each_benchmark.dart b/pkgs/pool/benchmark/for_each_benchmark.dart new file mode 100644 index 000000000..7438ace78 --- /dev/null +++ b/pkgs/pool/benchmark/for_each_benchmark.dart @@ -0,0 +1,51 @@ +import 'package:pool/pool.dart'; + +void main(List args) async { + var poolSize = args.isEmpty ? 5 : int.parse(args.first); + print('Pool size: $poolSize'); + + final pool = Pool(poolSize); + final watch = Stopwatch()..start(); + final start = DateTime.now(); + + DateTime lastLog; + Duration fastest; + int fastestIteration; + var i = 1; + + void log(bool force) { + var now = DateTime.now(); + if (force || + lastLog == null || + now.difference(lastLog) > const Duration(seconds: 1)) { + lastLog = now; + print([ + now.difference(start), + i.toString().padLeft(10), + fastestIteration.toString().padLeft(7), + fastest.inMicroseconds.toString().padLeft(9) + ].join(' ')); + } + } + + print(['Elapsed ', 'Iterations', 'Fastest', 'Time (us)'].join(' ')); + + for (;; i++) { + watch.reset(); + + var sum = await pool + .forEach(Iterable.generate(100000), (i) => i) + .reduce((a, b) => a + b); + + assert(sum == 4999950000, 'was $sum'); + + var elapsed = watch.elapsed; + if (fastest == null || fastest > elapsed) { + fastest = elapsed; + fastestIteration = i; + log(true); + } else { + log(false); + } + } +} From 41a61d57d361e1194c40f5a04c5d563969f9fe77 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 10 Jan 2019 15:49:29 -0800 Subject: [PATCH 115/281] fix `await null` in forEach Benchmark goes from ~54ms to ~33ms --- pkgs/pool/CHANGELOG.md | 5 +++++ pkgs/pool/lib/pool.dart | 4 +++- pkgs/pool/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 0c3d314a6..c680dd2bf 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.4.1 + +* `forEach`: Avoid `await null` if the `Stream` is not paused. + Improves trivial benchmark by 40%. + ## 1.4.0 * Add `forEach` to `Pool` to support efficient async processing of an diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 779300e2b..12dd5e1b0 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -170,7 +170,9 @@ class Pool { _resetTimer(); - await resumeCompleter?.future; + if (resumeCompleter != null) { + await resumeCompleter.future; + } if (cancelPending) { break; diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 35fb62dee..ebb05d9a2 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.4.0 +version: 1.4.1-dev description: >- Manage a finite pool of resources. From 99fa2b803d67c5d14fcaa781a9d9e76836d80d61 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 25 Feb 2019 11:16:14 -0800 Subject: [PATCH 116/281] Update time test expectation to account for runtime variations (dart-lang/pool#31) Fixes https://github.com/dart-lang/pool/issues/30 --- pkgs/pool/test/pool_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index d4d778992..77ef13d42 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -553,7 +553,7 @@ void main() { expect(finishedItems, itemCount); final expectedElapsed = - delayedToStringDuration.inMicroseconds * 3; + delayedToStringDuration.inMicroseconds * 4; expect((watch.elapsed ~/ itemCount).inMicroseconds, lessThan(expectedElapsed / (poolSize - otherTaskCount)), From 2c3ab9e81f1964ae27329b8a0ff4563c23b48208 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 23 May 2019 11:16:58 -0700 Subject: [PATCH 117/281] Fix missing_return violation newly enforced in Dart ~2.3.2-dev.0.1 --- pkgs/package_config/test/discovery_analysis_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart index c819a9074..e43245468 100644 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ b/pkgs/package_config/test/discovery_analysis_test.dart @@ -41,6 +41,7 @@ main() { var map = ctx.asMap(); expect(map.keys.map((dir) => dir.path), unorderedEquals([directory.path, fooDir.path, barDir.path])); + return null; }); } From 8f445e6466b64a9d232a72a4e11929e1678f8b54 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 21:03:52 -0700 Subject: [PATCH 118/281] Delete codereview.settings --- pkgs/pool/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/pool/codereview.settings diff --git a/pkgs/pool/codereview.settings b/pkgs/pool/codereview.settings deleted file mode 100644 index b474c08cb..000000000 --- a/pkgs/pool/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/pool/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From 393f6d532ba89ba6e23efef9772f26903cc56dde Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 21:06:27 -0700 Subject: [PATCH 119/281] Delete codereview.settings --- pkgs/package_config/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/package_config/codereview.settings diff --git a/pkgs/package_config/codereview.settings b/pkgs/package_config/codereview.settings deleted file mode 100644 index 1099f0594..000000000 --- a/pkgs/package_config/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: https://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/package_config/commit/ -CC_LIST: reviews@dartlang.org From 62c12f20026177ebdf7f6fa12040501ff867dbb9 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 16 Aug 2019 15:04:35 +0200 Subject: [PATCH 120/281] Add support for default package and metadata. (dart-lang/package_config#53) --- pkgs/package_config/CHANGELOG.md | 7 ++ .../lib/discovery_analysis.dart | 22 ++--- pkgs/package_config/lib/packages.dart | 36 ++++++++ pkgs/package_config/lib/packages_file.dart | 50 ++++++++--- .../package_config/lib/src/packages_impl.dart | 37 ++++++++- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/parse_test.dart | 82 ++++++++++++++++++- 7 files changed, 208 insertions(+), 28 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index e802d7deb..db4bb00d6 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.1.0 + +- Allow parsing files with default-package entries and metadata. + A default-package entry has an empty key and a valid package name + as value. + Metadata is attached as fragments to base URIs. + ## 1.0.5 - Fix usage of SDK constants. diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart index 67798e129..d623303c8 100644 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -59,22 +59,22 @@ abstract class PackageContext { static PackageContext findAll(Directory directory, {Packages root: Packages.noPackages}) { if (!directory.existsSync()) { - throw new ArgumentError("Directory not found: $directory"); + throw ArgumentError("Directory not found: $directory"); } var contexts = []; void findRoots(Directory directory) { Packages packages; List oldContexts; - File packagesFile = new File(path.join(directory.path, ".packages")); + File packagesFile = File(path.join(directory.path, ".packages")); if (packagesFile.existsSync()) { packages = _loadPackagesFile(packagesFile); oldContexts = contexts; contexts = []; } else { Directory packagesDir = - new Directory(path.join(directory.path, "packages")); + Directory(path.join(directory.path, "packages")); if (packagesDir.existsSync()) { - packages = new FilePackagesDirectoryPackages(packagesDir); + packages = FilePackagesDirectoryPackages(packagesDir); oldContexts = contexts; contexts = []; } @@ -87,7 +87,7 @@ abstract class PackageContext { } } if (packages != null) { - oldContexts.add(new _PackageContext(directory, packages, contexts)); + oldContexts.add(_PackageContext(directory, packages, contexts)); contexts = oldContexts; } } @@ -97,7 +97,7 @@ abstract class PackageContext { if (contexts.length == 1 && contexts[0].directory == directory) { return contexts[0]; } - return new _PackageContext(directory, root, contexts); + return _PackageContext(directory, root, contexts); } } @@ -106,10 +106,10 @@ class _PackageContext implements PackageContext { final Packages packages; final List children; _PackageContext(this.directory, this.packages, List children) - : children = new List.unmodifiable(children); + : children = List.unmodifiable(children); Map asMap() { - var result = new HashMap(); + var result = HashMap(); recurse(_PackageContext current) { result[current.directory] = current.packages; for (var child in current.children) { @@ -124,7 +124,7 @@ class _PackageContext implements PackageContext { PackageContext operator [](Directory directory) { String path = directory.path; if (!path.startsWith(this.directory.path)) { - throw new ArgumentError("Not inside $path: $directory"); + throw ArgumentError("Not inside $path: $directory"); } _PackageContext current = this; // The current path is know to agree with directory until deltaIndex. @@ -160,8 +160,8 @@ class _PackageContext implements PackageContext { } Packages _loadPackagesFile(File file) { - var uri = new Uri.file(file.path); + var uri = Uri.file(file.path); var bytes = file.readAsBytesSync(); var map = pkgfile.parse(bytes, uri); - return new MapPackages(map); + return MapPackages(map); } diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart index 890f4485c..886fbc83c 100644 --- a/pkgs/package_config/lib/packages.dart +++ b/pkgs/package_config/lib/packages.dart @@ -45,6 +45,32 @@ abstract class Packages { /// and getting `packages` from such a `Packages` object will throw. Iterable get packages; + /// Retrieve metadata associated with a package. + /// + /// Metadata have string keys and values, and are looked up by key. + /// + /// Returns `null` if the argument is not a valid package name, + /// or if the package is not one of the packages configured by + /// this packages object, or if the package does not have associated + /// metadata with the provided [key]. + /// + /// Not all `Packages` objects can support metadata. + /// Those will always return `null`. + String packageMetadata(String packageName, String key); + + /// Retrieve metadata associated with a library. + /// + /// If [libraryUri] is a `package:` URI, the returned value + /// is the same that would be returned by [packageMetadata] with + /// the package's name and the same key. + /// + /// If [libraryUri] is not a `package:` URI, and this [Packages] + /// object has a [defaultPackageName], then the [key] is looked + /// up on the default package instead. + /// + /// Otherwise the result is `null`. + String libraryMetadata(Uri libraryUri, String key); + /// Return the names-to-base-URI mapping of the available packages. /// /// Returns a map from package name to a base URI. @@ -55,4 +81,14 @@ abstract class Packages { /// Some `Packages` objects are unable to find the package names, /// and calling `asMap` on such a `Packages` object will throw. Map asMap(); + + /// The name of the "default package". + /// + /// A default package is a package that *non-package* libraries + /// may be considered part of for some purposes. + /// + /// The value is `null` if there is no default package. + /// Not all implementations of [Packages] supports a default package, + /// and will always have a `null` value for those. + String get defaultPackageName; } diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 85de1942d..284d8e90a 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -22,8 +22,15 @@ import "src/util.dart" show isValidPackageName; /// If the content was read from a file, `baseLocation` should be the /// location of that file. /// +/// If [allowDefaultPackage] is set to true, an entry with an empty package name +/// is accepted. This entry does not correspond to a package, but instead +/// represents a *default package* which non-package libraries may be considered +/// part of in some cases. The value of that entry must be a valid package name. +/// /// Returns a simple mapping from package name to package location. -Map parse(List source, Uri baseLocation) { +/// If default package is allowed, the map maps the empty string to the default package's name. +Map parse(List source, Uri baseLocation, + {bool allowDefaultPackage = false}) { int index = 0; Map result = {}; while (index < source.length) { @@ -36,7 +43,10 @@ Map parse(List source, Uri baseLocation) { continue; } if (char == $colon) { - throw new FormatException("Missing package name", source, index - 1); + if (!allowDefaultPackage) { + throw FormatException("Missing package name", source, index - 1); + } + separatorIndex = index - 1; } isComment = char == $hash; while (index < source.length) { @@ -50,22 +60,36 @@ Map parse(List source, Uri baseLocation) { } if (isComment) continue; if (separatorIndex < 0) { - throw new FormatException("No ':' on line", source, index - 1); + throw FormatException("No ':' on line", source, index - 1); } var packageName = new String.fromCharCodes(source, start, separatorIndex); - if (!isValidPackageName(packageName)) { - throw new FormatException("Not a valid package name", packageName, 0); + if (packageName.isEmpty + ? !allowDefaultPackage + : !isValidPackageName(packageName)) { + throw FormatException("Not a valid package name", packageName, 0); } - var packageUri = new String.fromCharCodes(source, separatorIndex + 1, end); - var packageLocation = Uri.parse(packageUri); - packageLocation = baseLocation.resolveUri(packageLocation); - if (!packageLocation.path.endsWith('/')) { - packageLocation = - packageLocation.replace(path: packageLocation.path + "/"); + var packageValue = + new String.fromCharCodes(source, separatorIndex + 1, end); + Uri packageLocation; + if (packageName.isEmpty) { + if (!isValidPackageName(packageValue)) { + throw FormatException( + "Default package entry value is not a valid package name"); + } + packageLocation = Uri(path: packageValue); + } else { + packageLocation = baseLocation.resolve(packageValue); + if (!packageLocation.path.endsWith('/')) { + packageLocation = + packageLocation.replace(path: packageLocation.path + "/"); + } } if (result.containsKey(packageName)) { - throw new FormatException( - "Same package name occured twice.", source, start); + if (packageName.isEmpty) { + throw FormatException( + "More than one default package entry", source, start); + } + throw FormatException("Same package name occured twice", source, start); } result[packageName] = packageLocation; } diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart index e89d94d22..817002f1e 100644 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -26,6 +26,12 @@ class NoPackages implements Packages { Iterable get packages => new Iterable.empty(); Map asMap() => const {}; + + String get defaultPackageName => null; + + String packageMetadata(String packageName, String key) => null; + + String libraryMetadata(Uri libraryUri, String key) => null; } /// Base class for [Packages] implementations. @@ -51,6 +57,12 @@ abstract class PackagesBase implements Packages { /// Returns `null` if no package exists with that name, and that can be /// determined. Uri getBase(String packageName); + + String get defaultPackageName => null; + + String packageMetadata(String packageName, String key) => null; + + String libraryMetadata(Uri libraryUri, String key) => null; } /// A [Packages] implementation based on an existing map. @@ -58,11 +70,34 @@ class MapPackages extends PackagesBase { final Map _mapping; MapPackages(this._mapping); - Uri getBase(String packageName) => _mapping[packageName]; + Uri getBase(String packageName) => + packageName.isEmpty ? null : _mapping[packageName]; Iterable get packages => _mapping.keys; Map asMap() => new UnmodifiableMapView(_mapping); + + String get defaultPackageName => _mapping[""]?.toString(); + + String packageMetadata(String packageName, String key) { + if (packageName.isEmpty) return null; + Uri uri = _mapping[packageName]; + if (uri == null || !uri.hasFragment) return null; + // This can be optimized, either by caching the map or by + // parsing incrementally instead of parsing the entire fragment. + return Uri.splitQueryString(uri.fragment)[key]; + } + + String libraryMetadata(Uri libraryUri, String key) { + if (libraryUri.isScheme("package")) { + return packageMetadata(libraryUri.pathSegments.first, key); + } + var defaultPackageNameUri = _mapping[""]; + if (defaultPackageNameUri != null) { + return packageMetadata(defaultPackageNameUri.toString(), key); + } + return null; + } } /// A [Packages] implementation based on a remote (e.g., HTTP) directory. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 4bad1cf52..a69096d58 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.0.5 +version: 1.1.0-pre description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index fb3a6fab4..b9b1bb510 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -116,6 +116,82 @@ main() { () => doParse(singleRelativeSample * 2, base), throwsFormatException); }); + test("disallow default package", () { + expect(() => doParse(":foo", base, allowDefaultPackage: false), + throwsFormatException); + }); + + test("allow default package", () { + var packages = doParse(":foo", base, allowDefaultPackage: true); + expect(packages.defaultPackageName, "foo"); + }); + + test("allow default package name with dot", () { + var packages = doParse(":foo.bar", base, allowDefaultPackage: true); + expect(packages.defaultPackageName, "foo.bar"); + }); + + test("not two default packages", () { + expect(() => doParse(":foo\n:bar", base, allowDefaultPackage: true), + throwsFormatException); + }); + + test("default package invalid package name", () { + // Not a valid *package name*. + expect(() => doParse(":foo/bar", base, allowDefaultPackage: true), + throwsFormatException); + }); + + group("metadata", () { + var packages = doParse( + ":foo\n" + "foo:foo#metafoo=1\n" + "bar:bar#metabar=2\n" + "baz:baz\n" + "qux:qux#metaqux1=3&metaqux2=4\n", + base, + allowDefaultPackage: true); + test("non-existing", () { + // non-package name. + expect(packages.packageMetadata("///", "f"), null); + expect(packages.packageMetadata("", "f"), null); + // unconfigured package name. + expect(packages.packageMetadata("absent", "f"), null); + // package name without that metadata + expect(packages.packageMetadata("foo", "notfoo"), null); + }); + test("lookup", () { + expect(packages.packageMetadata("foo", "metafoo"), "1"); + expect(packages.packageMetadata("bar", "metabar"), "2"); + expect(packages.packageMetadata("qux", "metaqux1"), "3"); + expect(packages.packageMetadata("qux", "metaqux2"), "4"); + }); + test("by library URI", () { + expect( + packages.libraryMetadata( + Uri.parse("package:foo/index.dart"), "metafoo"), + "1"); + expect( + packages.libraryMetadata( + Uri.parse("package:bar/index.dart"), "metabar"), + "2"); + expect( + packages.libraryMetadata( + Uri.parse("package:qux/index.dart"), "metaqux1"), + "3"); + expect( + packages.libraryMetadata( + Uri.parse("package:qux/index.dart"), "metaqux2"), + "4"); + }); + test("by default package", () { + expect( + packages.libraryMetadata( + Uri.parse("file:///whatever.dart"), "metafoo"), + "1"); + }); + }); + for (String invalidSample in invalid) { test("invalid '$invalidSample'", () { var result; @@ -130,8 +206,10 @@ main() { } } -Packages doParse(String sample, Uri baseUri) { - Map map = parse(sample.codeUnits, baseUri); +Packages doParse(String sample, Uri baseUri, + {bool allowDefaultPackage = false}) { + Map map = parse(sample.codeUnits, baseUri, + allowDefaultPackage: allowDefaultPackage); return new MapPackages(map); } From 95dada207519f41f974e8e63d7b702d47f8aff25 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 16 Aug 2019 15:06:22 +0200 Subject: [PATCH 121/281] Add .vscode/ to .gitignore. --- pkgs/package_config/.gitignore | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 pkgs/package_config/.gitignore diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore deleted file mode 100644 index e41fc1916..000000000 --- a/pkgs/package_config/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.packages -.pub -.dart_tool/ -packages -pubspec.lock -doc/api/ From 50a840de189ed8da8125df9d21763e8243eec849 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 16 Aug 2019 15:07:23 +0200 Subject: [PATCH 122/281] Readd .gitignore after deleting it. --- pkgs/package_config/.gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 pkgs/package_config/.gitignore diff --git a/pkgs/package_config/.gitignore b/pkgs/package_config/.gitignore new file mode 100644 index 000000000..7b888b84c --- /dev/null +++ b/pkgs/package_config/.gitignore @@ -0,0 +1,7 @@ +.packages +.pub +.dart_tool/ +.vscode/ +packages +pubspec.lock +doc/api/ From 375e28c38c17ca698999d1fd1fd3f383a5387a38 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 16 Aug 2019 15:08:45 +0200 Subject: [PATCH 123/281] Make version number ready for release. --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index a69096d58..b51932eb7 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.1.0-pre +version: 1.1.0 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config From 8e0739f064dabc72e9b2c218d829749e04c4ac9e Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Mon, 2 Sep 2019 14:06:28 +0200 Subject: [PATCH 124/281] Add support for writing defaultPackageName (dart-lang/package_config#54) --- pkgs/package_config/CHANGELOG.md | 3 ++ pkgs/package_config/lib/packages_file.dart | 22 ++++++++- pkgs/package_config/pubspec.yaml | 2 +- .../package_config/test/parse_write_test.dart | 47 ++++++++++++++++++- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index db4bb00d6..048eedf94 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.2.0 + - Added support for writing default-package entries. + ## 1.1.0 - Allow parsing files with default-package entries and metadata. diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 284d8e90a..1fa18e740 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -106,10 +106,15 @@ Map parse(List source, Uri baseLocation, /// If [baseUri] is provided, package locations will be made relative /// to the base URI, if possible, before writing. /// +/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an +/// empty string mapping to the _default package name_. +/// /// All the keys of [packageMapping] must be valid package names, /// and the values must be URIs that do not have the `package:` scheme. void write(StringSink output, Map packageMapping, - {Uri baseUri, String comment}) { + {Uri baseUri, String comment, bool allowDefaultPackage = false}) { + ArgumentError.checkNotNull(allowDefaultPackage, 'allowDefaultPackage'); + if (baseUri != null && !baseUri.isAbsolute) { throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); } @@ -128,6 +133,21 @@ void write(StringSink output, Map packageMapping, } packageMapping.forEach((String packageName, Uri uri) { + // If [packageName] is empty then [uri] is the _default package name_. + if (allowDefaultPackage && packageName.isEmpty) { + final defaultPackageName = uri.toString(); + if (!isValidPackageName(defaultPackageName)) { + throw ArgumentError.value( + defaultPackageName, + 'defaultPackageName', + '"$defaultPackageName" is not a valid package name', + ); + } + output.write(':'); + output.write(defaultPackageName); + output.writeln(); + return; + } // Validate packageName. if (!isValidPackageName(packageName)) { throw new ArgumentError('"$packageName" is not a valid package name'); diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index b51932eb7..72d299bf2 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.1.0 +version: 1.2.0 description: Support for working with Package Resolution config files. author: Dart Team homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart index b963eb5b5..415b479e9 100644 --- a/pkgs/package_config/test/parse_write_test.dart +++ b/pkgs/package_config/test/parse_write_test.dart @@ -4,6 +4,7 @@ library package_config.parse_write_test; +import "dart:convert" show utf8; import "package:package_config/packages_file.dart"; import "package:test/test.dart"; @@ -32,6 +33,40 @@ main() { var resultMap = parse(content, packagesFile); expect(resultMap, map); }); + + test("write with defaultPackageName", () { + var content = writeToString( + {'': Uri.parse('my_pkg')}..addAll(map), + allowDefaultPackage: true, + ).codeUnits; + var resultMap = parse( + content, + packagesFile, + allowDefaultPackage: true, + ); + expect(resultMap[''].toString(), 'my_pkg'); + expect( + resultMap, + {'': Uri.parse('my_pkg')}..addAll(map), + ); + }); + + test("write with defaultPackageName (utf8)", () { + var content = utf8.encode(writeToString( + {'': Uri.parse('my_pkg')}..addAll(map), + allowDefaultPackage: true, + )); + var resultMap = parse( + content, + packagesFile, + allowDefaultPackage: true, + ); + expect(resultMap[''].toString(), 'my_pkg'); + expect( + resultMap, + {'': Uri.parse('my_pkg')}..addAll(map), + ); + }); }); } @@ -82,8 +117,16 @@ main() { }); } -String writeToString(Map map, {Uri baseUri, String comment}) { +String writeToString( + Map map, { + Uri baseUri, + String comment, + bool allowDefaultPackage = false, +}) { var buffer = new StringBuffer(); - write(buffer, map, baseUri: baseUri, comment: comment); + write(buffer, map, + baseUri: baseUri, + comment: comment, + allowDefaultPackage: allowDefaultPackage); return buffer.toString(); } From fc6f50e6d9bde8135d3f4dbeea28d31eca8c5c7d Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Mon, 2 Sep 2019 15:54:17 +0200 Subject: [PATCH 125/281] Fix trailing slash logic when writing .packages (dart-lang/package_config#55) --- pkgs/package_config/CHANGELOG.md | 1 + pkgs/package_config/lib/packages_file.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 048eedf94..50f1ede5a 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,5 +1,6 @@ ## 1.2.0 - Added support for writing default-package entries. + - Fixed bug when writing `Uri`s containing a fragment. ## 1.1.0 diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart index 1fa18e740..1c35d5b21 100644 --- a/pkgs/package_config/lib/packages_file.dart +++ b/pkgs/package_config/lib/packages_file.dart @@ -162,10 +162,10 @@ void write(StringSink output, Map packageMapping, if (baseUri != null) { uri = _relativize(uri, baseUri); } - output.write(uri); if (!uri.path.endsWith('/')) { - output.write('/'); + uri = uri.replace(path: uri.path + '/'); } + output.write(uri); output.writeln(); }); } From 5b1b9835308b69b8ee18d2e08bfa8ac8fd585521 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 9 Dec 2019 15:59:31 -0800 Subject: [PATCH 126/281] Fix newly enforced package:pedantic lints (dart-lang/pool#34) - prefer_single_quotes --- pkgs/pool/lib/pool.dart | 12 +++---- pkgs/pool/test/pool_test.dart | 66 +++++++++++++++++------------------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 12dd5e1b0..d8565411a 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -97,7 +97,7 @@ class Pool { /// until one of them is released. Future request() { if (isClosed) { - throw StateError("request() may not be called on a closed Pool."); + throw StateError('request() may not be called on a closed Pool.'); } if (_allocatedResources < _maxAllocatedResources) { @@ -119,7 +119,7 @@ class Pool { /// The return value of [callback] is piped to the returned Future. Future withResource(FutureOr Function() callback) async { if (isClosed) { - throw StateError("withResource() may not be called on a closed Pool."); + throw StateError('withResource() may not be called on a closed Pool.'); } var resource = await request(); @@ -324,8 +324,8 @@ class Pool { for (var completer in _requestedResources) { completer.completeError( TimeoutException( - "Pool deadlock: all resources have been " - "allocated for too long.", + 'Pool deadlock: all resources have been ' + 'allocated for too long.', _timeout), Chain.current()); } @@ -350,7 +350,7 @@ class PoolResource { /// no longer allocated, and that a new [PoolResource] may be allocated. void release() { if (_released) { - throw StateError("A PoolResource may only be released once."); + throw StateError('A PoolResource may only be released once.'); } _released = true; _pool._onResourceReleased(); @@ -370,7 +370,7 @@ class PoolResource { /// may be complete, but it could still emit asynchronous errors. void allowRelease(Function() onRelease) { if (_released) { - throw StateError("A PoolResource may only be released once."); + throw StateError('A PoolResource may only be released once.'); } _released = true; _pool._onResourceReleaseAllowed(onRelease); diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 77ef13d42..091cd5513 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -11,15 +11,15 @@ import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; void main() { - group("request()", () { - test("resources can be requested freely up to the limit", () { + group('request()', () { + test('resources can be requested freely up to the limit', () { var pool = Pool(50); for (var i = 0; i < 50; i++) { expect(pool.request(), completes); } }); - test("resources block past the limit", () { + test('resources block past the limit', () { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 50; i++) { @@ -31,7 +31,7 @@ void main() { }); }); - test("a blocked resource is allocated when another is released", () { + test('a blocked resource is allocated when another is released', () { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 49; i++) { @@ -52,15 +52,15 @@ void main() { }); }); - group("withResource()", () { - test("can be called freely up to the limit", () { + group('withResource()', () { + test('can be called freely up to the limit', () { var pool = Pool(50); for (var i = 0; i < 50; i++) { pool.withResource(expectAsync0(() => Completer().future)); } }); - test("blocks the callback past the limit", () { + test('blocks the callback past the limit', () { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 50; i++) { @@ -72,7 +72,7 @@ void main() { }); }); - test("a blocked resource is allocated when another is released", () { + test('a blocked resource is allocated when another is released', () { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 49; i++) { @@ -99,14 +99,14 @@ void main() { }); // Regression test for #3. - test("can be called immediately before close()", () async { + test('can be called immediately before close()', () async { var pool = Pool(1); unawaited(pool.withResource(expectAsync0(() {}))); await pool.close(); }); }); - group("with a timeout", () { + group('with a timeout', () { test("doesn't time out if there are no pending requests", () { FakeAsync().run((async) { var pool = Pool(50, timeout: const Duration(seconds: 5)); @@ -118,7 +118,7 @@ void main() { }); }); - test("resets the timer if a resource is returned", () { + test('resets the timer if a resource is returned', () { FakeAsync().run((async) { var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 49; i++) { @@ -139,7 +139,7 @@ void main() { }); }); - test("resets the timer if a resource is requested", () { + test('resets the timer if a resource is requested', () { FakeAsync().run((async) { var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 50; i++) { @@ -155,7 +155,7 @@ void main() { }); }); - test("times out if nothing happens", () { + test('times out if nothing happens', () { FakeAsync().run((async) { var pool = Pool(50, timeout: const Duration(seconds: 5)); for (var i = 0; i < 50; i++) { @@ -168,8 +168,8 @@ void main() { }); }); - group("allowRelease()", () { - test("runs the callback once the resource limit is exceeded", () async { + group('allowRelease()', () { + test('runs the callback once the resource limit is exceeded', () async { var pool = Pool(50); for (var i = 0; i < 49; i++) { expect(pool.request(), completes); @@ -186,7 +186,7 @@ void main() { expect(onReleaseCalled, isTrue); }); - test("runs the callback immediately if there are blocked requests", + test('runs the callback immediately if there are blocked requests', () async { var pool = Pool(1); var resource = await pool.request(); @@ -200,7 +200,7 @@ void main() { expect(onReleaseCalled, isTrue); }); - test("blocks the request until the callback completes", () async { + test('blocks the request until the callback completes', () async { var pool = Pool(1); var resource = await pool.request(); @@ -217,7 +217,7 @@ void main() { expect(requestComplete, isTrue); }); - test("completes requests in request order regardless of callback order", + test('completes requests in request order regardless of callback order', () async { var pool = Pool(2); var resource1 = await pool.request(); @@ -262,7 +262,7 @@ void main() { expect(request2Complete, isTrue); }); - test("runs onRequest in the zone it was created", () async { + test('runs onRequest in the zone it was created', () async { var pool = Pool(1); var resource = await pool.request(); @@ -290,14 +290,14 @@ void main() { await Future.delayed(Duration.zero); }); - group("close()", () { - test("disallows request() and withResource()", () { + group('close()', () { + test('disallows request() and withResource()', () { var pool = Pool(1)..close(); expect(pool.request, throwsStateError); expect(() => pool.withResource(() {}), throwsStateError); }); - test("pending requests are fulfilled", () async { + test('pending requests are fulfilled', () async { var pool = Pool(1); var resource1 = await pool.request(); expect( @@ -310,7 +310,7 @@ void main() { resource1.release(); }); - test("pending requests are fulfilled with allowRelease", () async { + test('pending requests are fulfilled with allowRelease', () async { var pool = Pool(1); var resource1 = await pool.request(); @@ -359,7 +359,7 @@ void main() { resource3.release(); }); - test("active onReleases complete as usual", () async { + test('active onReleases complete as usual', () async { var pool = Pool(1); var resource = await pool.request(); @@ -380,7 +380,7 @@ void main() { completer.complete(); }); - test("inactive onReleases fire", () async { + test('inactive onReleases fire', () async { var pool = Pool(2); var resource1 = await pool.request(); var resource2 = await pool.request(); @@ -404,7 +404,7 @@ void main() { completer2.complete(); }); - test("new allowReleases fire immediately", () async { + test('new allowReleases fire immediately', () async { var pool = Pool(1); var resource = await pool.request(); @@ -422,18 +422,18 @@ void main() { completer.complete(); }); - test("an onRelease error is piped to the return value", () async { + test('an onRelease error is piped to the return value', () async { var pool = Pool(1); var resource = await pool.request(); var completer = Completer(); resource.allowRelease(() => completer.future); - expect(pool.done, throwsA("oh no!")); - expect(pool.close(), throwsA("oh no!")); + expect(pool.done, throwsA('oh no!')); + expect(pool.close(), throwsA('oh no!')); await Future.delayed(Duration.zero); - completer.completeError("oh no!"); + completer.completeError('oh no!'); }); }); @@ -719,7 +719,7 @@ void main() { }); }); - test("throw error when pool limit <= 0", () { + test('throw error when pool limit <= 0', () { expect(() => Pool(-1), throwsArgumentError); expect(() => Pool(0), throwsArgumentError); }); @@ -731,7 +731,7 @@ void main() { void Function() expectNoAsync() { var stack = Trace.current(1); return () => registerException( - TestFailure("Expected function not to be called."), stack); + TestFailure('Expected function not to be called.'), stack); } /// A matcher for Futures that asserts that they don't complete. @@ -742,6 +742,6 @@ Matcher get doesNotComplete => predicate((future) { var stack = Trace.current(1); future.then((_) => registerException( - TestFailure("Expected future not to complete."), stack)); + TestFailure('Expected future not to complete.'), stack)); return true; }); From c0466fe4af21b652c54dcb1d6eea2777de5c8670 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 20 Dec 2019 14:50:27 +0100 Subject: [PATCH 127/281] Version 2.0.0 supporting package_config.json (dart-lang/package_config#56) Giving it the package name package_config_2 to avoid conflict with the existing package_config which is used by the `test` package. This is the initial version. It will be updated to allow overlapping packages, as long as no file in the package URI root can be considered as belonging to a different package. --- pkgs/package_config/CHANGELOG.md | 3 + pkgs/package_config/CONTRIBUTING.md | 2 +- pkgs/package_config/LICENSE | 2 +- pkgs/package_config/lib/discovery.dart | 230 -------- .../lib/discovery_analysis.dart | 167 ------ pkgs/package_config/lib/package_config.dart | 141 +++++ pkgs/package_config/lib/packages.dart | 94 ---- pkgs/package_config/lib/packages_file.dart | 232 -------- pkgs/package_config/lib/src/discovery.dart | 132 +++++ pkgs/package_config/lib/src/errors.dart | 24 + .../lib/src/package_config.dart | 176 ++++++ .../lib/src/package_config_impl.dart | 181 +++++++ .../lib/src/package_config_json.dart | 327 ++++++++++++ .../package_config/lib/src/packages_file.dart | 150 ++++++ .../package_config/lib/src/packages_impl.dart | 127 ----- .../lib/src/packages_io_impl.dart | 45 -- pkgs/package_config/lib/src/util.dart | 251 ++++++++- pkgs/package_config/pubspec.yaml | 8 +- pkgs/package_config/test/all.dart | 17 - .../test/discovery_analysis_test.dart | 126 ----- pkgs/package_config/test/discovery_test.dart | 485 +++++++---------- .../test/discovery_uri_test.dart | 256 +++++++++ pkgs/package_config/test/parse_test.dart | 503 ++++++++++-------- .../package_config/test/parse_write_test.dart | 132 ----- pkgs/package_config/test/src/util.dart | 109 ++++ 25 files changed, 2223 insertions(+), 1697 deletions(-) delete mode 100644 pkgs/package_config/lib/discovery.dart delete mode 100644 pkgs/package_config/lib/discovery_analysis.dart create mode 100644 pkgs/package_config/lib/package_config.dart delete mode 100644 pkgs/package_config/lib/packages.dart delete mode 100644 pkgs/package_config/lib/packages_file.dart create mode 100644 pkgs/package_config/lib/src/discovery.dart create mode 100644 pkgs/package_config/lib/src/errors.dart create mode 100644 pkgs/package_config/lib/src/package_config.dart create mode 100644 pkgs/package_config/lib/src/package_config_impl.dart create mode 100644 pkgs/package_config/lib/src/package_config_json.dart create mode 100644 pkgs/package_config/lib/src/packages_file.dart delete mode 100644 pkgs/package_config/lib/src/packages_impl.dart delete mode 100644 pkgs/package_config/lib/src/packages_io_impl.dart delete mode 100644 pkgs/package_config/test/all.dart delete mode 100644 pkgs/package_config/test/discovery_analysis_test.dart create mode 100644 pkgs/package_config/test/discovery_uri_test.dart delete mode 100644 pkgs/package_config/test/parse_write_test.dart create mode 100644 pkgs/package_config/test/src/util.dart diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 50f1ede5a..84384fc21 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2.0.0 + - Based on new JSON file format with more content. + ## 1.2.0 - Added support for writing default-package entries. - Fixed bug when writing `Uri`s containing a fragment. diff --git a/pkgs/package_config/CONTRIBUTING.md b/pkgs/package_config/CONTRIBUTING.md index 6f5e0ea67..8423ff94f 100644 --- a/pkgs/package_config/CONTRIBUTING.md +++ b/pkgs/package_config/CONTRIBUTING.md @@ -23,7 +23,7 @@ All submissions, including submissions by project members, require review. ### File headers All files in the project must start with the following header. - // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // Copyright (c) 2019, 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. diff --git a/pkgs/package_config/LICENSE b/pkgs/package_config/LICENSE index de31e1a0a..f75d7c237 100644 --- a/pkgs/package_config/LICENSE +++ b/pkgs/package_config/LICENSE @@ -1,4 +1,4 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2019, the Dart project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart deleted file mode 100644 index 57584b682..000000000 --- a/pkgs/package_config/lib/discovery.dart +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2015, 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 package_config.discovery; - -import "dart:async"; -import "dart:io"; -import "dart:typed_data" show Uint8List; - -import "package:path/path.dart" as path; - -import "packages.dart"; -import "packages_file.dart" as pkgfile show parse; -import "src/packages_impl.dart"; -import "src/packages_io_impl.dart"; - -/// Reads a package resolution file and creates a [Packages] object from it. -/// -/// The [packagesFile] must exist and be loadable. -/// Currently that means the URI must have a `file`, `http` or `https` scheme, -/// and that the file can be loaded and its contents parsed correctly. -/// -/// If the [loader] is provided, it is used to fetch non-`file` URIs, and -/// it can support other schemes or set up more complex HTTP requests. -/// -/// This function can be used to load an explicitly configured package -/// resolution file, for example one specified using a `--packages` -/// command-line parameter. -Future loadPackagesFile(Uri packagesFile, - {Future> loader(Uri uri)}) async { - Packages parseBytes(List bytes) { - Map packageMap = pkgfile.parse(bytes, packagesFile); - return new MapPackages(packageMap); - } - - if (packagesFile.scheme == "file") { - File file = new File.fromUri(packagesFile); - return parseBytes(await file.readAsBytes()); - } - if (loader == null) { - return parseBytes(await _httpGet(packagesFile)); - } - return parseBytes(await loader(packagesFile)); -} - -/// Create a [Packages] object for a package directory. -/// -/// The [packagesDir] URI should refer to a directory. -/// Package names are resolved as relative to sub-directories of the -/// package directory. -/// -/// This function can be used for explicitly configured package directories, -/// for example one specified using a `--package-root` comand-line parameter. -Packages getPackagesDirectory(Uri packagesDir) { - if (packagesDir.scheme == "file") { - Directory directory = new Directory.fromUri(packagesDir); - return new FilePackagesDirectoryPackages(directory); - } - if (!packagesDir.path.endsWith('/')) { - packagesDir = packagesDir.replace(path: packagesDir.path + '/'); - } - return new NonFilePackagesDirectoryPackages(packagesDir); -} - -/// Discover the package configuration for a Dart script. -/// -/// The [baseUri] points to either the Dart script or its directory. -/// A package resolution strategy is found by going through the following steps, -/// and stopping when something is found. -/// -/// * Check if a `.packages` file exists in the same directory. -/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory -/// in the same directory, and resolve packages relative to that. -/// * If `baseUri`'s scheme *is* `file`: -/// * Check if a `packages` directory exists. -/// * Otherwise check each successive parent directory of `baseUri` for a -/// `.packages` file. -/// -/// If any of these tests succeed, a `Packages` class is returned. -/// Returns the constant [noPackages] if no resolution strategy is found. -/// -/// This function currently only supports `file`, `http` and `https` URIs. -/// It needs to be able to load a `.packages` file from the URI, so only -/// recognized schemes are accepted. -/// -/// To support other schemes, or more complex HTTP requests, -/// an optional [loader] function can be supplied. -/// It's called to load the `.packages` file for a non-`file` scheme. -/// The loader function returns the *contents* of the file -/// identified by the URI it's given. -/// The content should be a UTF-8 encoded `.packages` file, and must return an -/// error future if loading fails for any reason. -Future findPackages(Uri baseUri, - {Future> loader(Uri unsupportedUri)}) { - if (baseUri.scheme == "file") { - return new Future.sync(() => findPackagesFromFile(baseUri)); - } else if (loader != null) { - return findPackagesFromNonFile(baseUri, loader: loader); - } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, loader: _httpGet); - } else { - return new Future.value(Packages.noPackages); - } -} - -/// Find the location of the package resolution file/directory for a Dart file. -/// -/// Checks for a `.packages` file in the [workingDirectory]. -/// If not found, checks for a `packages` directory in the same directory. -/// If still not found, starts checking parent directories for -/// `.packages` until reaching the root directory. -/// -/// Returns a [File] object of a `.packages` file if one is found, or a -/// [Directory] object for the `packages/` directory if that is found. -FileSystemEntity _findPackagesFile(String workingDirectory) { - var dir = new Directory(workingDirectory); - if (!dir.isAbsolute) dir = dir.absolute; - if (!dir.existsSync()) { - throw new ArgumentError.value( - workingDirectory, "workingDirectory", "Directory does not exist."); - } - File checkForConfigFile(Directory directory) { - assert(directory.isAbsolute); - var file = new File(path.join(directory.path, ".packages")); - if (file.existsSync()) return file; - return null; - } - - // Check for $cwd/.packages - var packagesCfgFile = checkForConfigFile(dir); - if (packagesCfgFile != null) return packagesCfgFile; - // Check for $cwd/packages/ - var packagesDir = new Directory(path.join(dir.path, "packages")); - if (packagesDir.existsSync()) return packagesDir; - // Check for cwd(/..)+/.packages - var parentDir = dir.parent; - while (parentDir.path != dir.path) { - packagesCfgFile = checkForConfigFile(parentDir); - if (packagesCfgFile != null) break; - dir = parentDir; - parentDir = dir.parent; - } - return packagesCfgFile; -} - -/// Finds a package resolution strategy for a local Dart script. -/// -/// The [fileBaseUri] points to either a Dart script or the directory of the -/// script. The `fileBaseUri` must be a `file:` URI. -/// -/// This function first tries to locate a `.packages` file in the `fileBaseUri` -/// directory. If that is not found, it instead checks for the presence of -/// a `packages/` directory in the same place. -/// If that also fails, it starts checking parent directories for a `.packages` -/// file, and stops if it finds it. -/// Otherwise it gives up and returns [Packages.noPackages]. -Packages findPackagesFromFile(Uri fileBaseUri) { - Uri baseDirectoryUri = fileBaseUri; - if (!fileBaseUri.path.endsWith('/')) { - baseDirectoryUri = baseDirectoryUri.resolve("."); - } - String baseDirectoryPath = baseDirectoryUri.toFilePath(); - FileSystemEntity location = _findPackagesFile(baseDirectoryPath); - if (location == null) return Packages.noPackages; - if (location is File) { - List fileBytes = location.readAsBytesSync(); - Map map = - pkgfile.parse(fileBytes, new Uri.file(location.path)); - return new MapPackages(map); - } - assert(location is Directory); - return new FilePackagesDirectoryPackages(location); -} - -/// Finds a package resolution strategy for a Dart script. -/// -/// The [nonFileUri] points to either a Dart script or the directory of the -/// script. -/// The [nonFileUri] should not be a `file:` URI since the algorithm for -/// finding a package resolution strategy is more elaborate for `file:` URIs. -/// In that case, use [findPackagesFromFile]. -/// -/// This function first tries to locate a `.packages` file in the [nonFileUri] -/// directory. If that is not found, it instead assumes a `packages/` directory -/// in the same place. -/// -/// By default, this function only works for `http:` and `https:` URIs. -/// To support other schemes, a loader must be provided, which is used to -/// try to load the `.packages` file. The loader should return the contents -/// of the requested `.packages` file as bytes, which will be assumed to be -/// UTF-8 encoded. -Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) async { - if (loader == null) loader = _httpGet; - Uri packagesFileUri = nonFileUri.resolve(".packages"); - - try { - List fileBytes = await loader(packagesFileUri); - Map map = pkgfile.parse(fileBytes, packagesFileUri); - return new MapPackages(map); - } catch (_) { - // Didn't manage to load ".packages". Assume a "packages/" directory. - Uri packagesDirectoryUri = nonFileUri.resolve("packages/"); - return new NonFilePackagesDirectoryPackages(packagesDirectoryUri); - } -} - -/// Fetches a file over http. -Future> _httpGet(Uri uri) async { - HttpClient client = new HttpClient(); - HttpClientRequest request = await client.getUrl(uri); - HttpClientResponse response = await request.close(); - if (response.statusCode != HttpStatus.ok) { - throw new HttpException('${response.statusCode} ${response.reasonPhrase}', - uri: uri); - } - List> splitContent = await response.toList(); - int totalLength = 0; - for (var list in splitContent) { - totalLength += list.length; - } - Uint8List result = new Uint8List(totalLength); - int offset = 0; - for (List contentPart in splitContent) { - result.setRange(offset, offset + contentPart.length, contentPart); - offset += contentPart.length; - } - return result; -} diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart deleted file mode 100644 index d623303c8..000000000 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Analyse a directory structure and find packages resolvers for each -/// sub-directory. -/// -/// The resolvers are generally the same that would be found by using -/// the `discovery.dart` library on each sub-directory in turn, -/// but more efficiently and with some heuristics for directories that -/// wouldn't otherwise have a package resolution strategy, or that are -/// determined to be "package directories" themselves. -library package_config.discovery_analysis; - -import "dart:collection" show HashMap; -import "dart:io" show File, Directory; - -import "package:path/path.dart" as path; - -import "packages.dart"; -import "packages_file.dart" as pkgfile; -import "src/packages_impl.dart"; -import "src/packages_io_impl.dart"; - -/// Associates a [Packages] package resolution strategy with a directory. -/// -/// The package resolution applies to the directory and any sub-directory -/// that doesn't have its own overriding child [PackageContext]. -abstract class PackageContext { - /// The directory that introduced the [packages] resolver. - Directory get directory; - - /// A [Packages] resolver that applies to the directory. - /// - /// Introduced either by a `.packages` file or a `packages/` directory. - Packages get packages; - - /// Child contexts that apply to sub-directories of [directory]. - List get children; - - /// Look up the [PackageContext] that applies to a specific directory. - /// - /// The directory must be inside [directory]. - PackageContext operator [](Directory directory); - - /// A map from directory to package resolver. - /// - /// Has an entry for this package context and for each child context - /// contained in this one. - Map asMap(); - - /// Analyze [directory] and sub-directories for package resolution strategies. - /// - /// Returns a mapping from sub-directories to [Packages] objects. - /// - /// The analysis assumes that there are no `.packages` files in a parent - /// directory of `directory`. If there is, its corresponding `Packages` object - /// should be provided as `root`. - static PackageContext findAll(Directory directory, - {Packages root: Packages.noPackages}) { - if (!directory.existsSync()) { - throw ArgumentError("Directory not found: $directory"); - } - var contexts = []; - void findRoots(Directory directory) { - Packages packages; - List oldContexts; - File packagesFile = File(path.join(directory.path, ".packages")); - if (packagesFile.existsSync()) { - packages = _loadPackagesFile(packagesFile); - oldContexts = contexts; - contexts = []; - } else { - Directory packagesDir = - Directory(path.join(directory.path, "packages")); - if (packagesDir.existsSync()) { - packages = FilePackagesDirectoryPackages(packagesDir); - oldContexts = contexts; - contexts = []; - } - } - for (var entry in directory.listSync()) { - if (entry is Directory) { - if (packages == null || !entry.path.endsWith("/packages")) { - findRoots(entry); - } - } - } - if (packages != null) { - oldContexts.add(_PackageContext(directory, packages, contexts)); - contexts = oldContexts; - } - } - - findRoots(directory); - // If the root is not itself context root, add a the wrapper context. - if (contexts.length == 1 && contexts[0].directory == directory) { - return contexts[0]; - } - return _PackageContext(directory, root, contexts); - } -} - -class _PackageContext implements PackageContext { - final Directory directory; - final Packages packages; - final List children; - _PackageContext(this.directory, this.packages, List children) - : children = List.unmodifiable(children); - - Map asMap() { - var result = HashMap(); - recurse(_PackageContext current) { - result[current.directory] = current.packages; - for (var child in current.children) { - recurse(child); - } - } - - recurse(this); - return result; - } - - PackageContext operator [](Directory directory) { - String path = directory.path; - if (!path.startsWith(this.directory.path)) { - throw ArgumentError("Not inside $path: $directory"); - } - _PackageContext current = this; - // The current path is know to agree with directory until deltaIndex. - int deltaIndex = current.directory.path.length; - List children = current.children; - int i = 0; - while (i < children.length) { - // TODO(lrn): Sort children and use binary search. - _PackageContext child = children[i]; - String childPath = child.directory.path; - if (_stringsAgree(path, childPath, deltaIndex, childPath.length)) { - deltaIndex = childPath.length; - if (deltaIndex == path.length) { - return child; - } - current = child; - children = current.children; - i = 0; - continue; - } - i++; - } - return current; - } - - static bool _stringsAgree(String a, String b, int start, int end) { - if (a.length < end || b.length < end) return false; - for (int i = start; i < end; i++) { - if (a.codeUnitAt(i) != b.codeUnitAt(i)) return false; - } - return true; - } -} - -Packages _loadPackagesFile(File file) { - var uri = Uri.file(file.path); - var bytes = file.readAsBytesSync(); - var map = pkgfile.parse(bytes, uri); - return MapPackages(map); -} diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart new file mode 100644 index 000000000..4d6f346d7 --- /dev/null +++ b/pkgs/package_config/lib/package_config.dart @@ -0,0 +1,141 @@ +// Copyright (c) 2019, 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. + +/// A package configuration is a way to assign file paths to package URIs, +/// and vice-versa, +library package_config.package_config; + +import "dart:io" show File, Directory; +import "dart:typed_data" show Uint8List; +import "src/discovery.dart" as discover; +import "src/package_config.dart"; +import "src/package_config_json.dart"; + +export "src/package_config.dart" show PackageConfig, Package; +export "src/errors.dart" show PackageConfigError; + +/// Reads a specific package configuration file. +/// +/// The file must exist and be readable. +/// It must be either a valid `package_config.json` file +/// or a valid `.packages` file. +/// It is considered a `package_config.json` file if its first character +/// is a `{`. +/// +/// If the file is a `.packages` file, also checks if there is a +/// `.dart_tool/package_config.json` file next to the original file, +/// and if so, loads that instead. +Future loadPackageConfig(File file) => readAnyConfigFile(file); + +/// Reads a specific package configuration URI. +/// +/// The file of the URI must exist and be readable. +/// It must be either a valid `package_config.json` file +/// or a valid `.packages` file. +/// It is considered a `package_config.json` file if its first +/// non-whitespace character is a `{`. +/// +/// If the file is a `.packages` file, first checks if there is a +/// `.dart_tool/package_config.json` file next to the original file, +/// and if so, loads that instead. +/// The [file] *must not* be a `package:` URI. +/// +/// If [loader] is provided, URIs are loaded using that function. +/// The future returned by the loader must complete with a [Uint8List] +/// containing the entire file content, +/// or with `null` if the file does not exist. +/// The loader may throw at its own discretion, for situations where +/// it determines that an error might be need user attention, +/// but it is always allowed to return `null`. +/// This function makes no attempt to catch such errors. +/// +/// If no [loader] is supplied, a default loader is used which +/// only accepts `file:`, `http:` and `https:` URIs, +/// and which uses the platform file system and HTTP requests to +/// fetch file content. The default loader never throws because +/// of an I/O issue, as long as the location URIs are valid. +/// As such, it does not distinguish between a file not existing, +/// and it being temporarily locked or unreachable. +Future loadPackageConfigUri(Uri file, + {Future loader(Uri uri) /*?*/}) => + readAnyConfigFileUri(file, loader); + +/// Finds a package configuration relative to [directory]. +/// +/// If [directory] contains a package configuration, +/// either a `.dart_tool/package_config.json` file or, +/// if not, a `.packages`, then that file is loaded. +/// +/// If no file is found in the current directory, +/// then the parent directories are checked recursively, +/// all the way to the root directory, to check if those contains +/// a package configuration. +/// If [recurse] is set to [false], this parent directory check is not +/// performed. +/// +/// Returns `null` if no configuration file is found. +Future findPackageConfig(Directory directory, + {bool recurse = true}) => + discover.findPackageConfig(directory, recurse); + +/// Finds a package configuration relative to [location]. +/// +/// If [location] contains a package configuration, +/// either a `.dart_tool/package_config.json` file or, +/// if not, a `.packages`, then that file is loaded. +/// The [location] URI *must not* be a `package:` URI. +/// It should be a hierarchical URI which is supported +/// by [loader]. +/// +/// If no file is found in the current directory, +/// then the parent directories are checked recursively, +/// all the way to the root directory, to check if those contains +/// a package configuration. +/// If [recurse] is set to [false], this parent directory check is not +/// performed. +/// +/// If [loader] is provided, URIs are loaded using that function. +/// The future returned by the loader must complete with a [Uint8List] +/// containing the entire file content, +/// or with `null` if the file does not exist. +/// The loader may throw at its own discretion, for situations where +/// it determines that an error might be need user attention, +/// but it is always allowed to return `null`. +/// This function makes no attempt to catch such errors. +/// +/// If no [loader] is supplied, a default loader is used which +/// only accepts `file:`, `http:` and `https:` URIs, +/// and which uses the platform file system and HTTP requests to +/// fetch file content. The default loader never throws because +/// of an I/O issue, as long as the location URIs are valid. +/// As such, it does not distinguish between a file not existing, +/// and it being temporarily locked or unreachable. +/// +/// Returns `null` if no configuration file is found. +Future findPackageConfigUri(Uri location, + {bool recurse = true, Future loader(Uri uri)}) => + discover.findPackageConfigUri(location, loader, recurse); + +/// Writes a package configuration to the provided directory. +/// +/// Writes `.dart_tool/package_config.json` relative to [directory]. +/// If the `.dart_tool/` directory does not exist, it is created. +/// If it cannot be created, this operation fails. +/// +/// If [extraData] contains any entries, they are added to the JSON +/// written to the `package_config.json` file. Entries with the names +/// `"configVersion"` or `"packages"` are ignored, all other entries +/// are added verbatim. +/// This is intended for, e.g., the +/// `"generator"`, `"generated"` and `"generatorVersion"` +/// properties. +/// +/// Also writes a `.packages` file in [directory]. +/// This will stop happening eventually as the `.packages` file becomes +/// discontinued. +/// A comment is generated if `[PackageConfig.extraData]` contains a +/// `"generator"` entry. +Future savePackageConfig( + PackageConfig configuration, Directory directory) => + writePackageConfigJson(configuration, directory); diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart deleted file mode 100644 index 886fbc83c..000000000 --- a/pkgs/package_config/lib/packages.dart +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2015, 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 package_config.packages; - -import "src/packages_impl.dart"; - -/// A package resolution strategy. -/// -/// Allows converting a `package:` URI to a different kind of URI. -/// -/// May also allow listing the available packages and converting -/// to a `Map` that gives the base location of each available -/// package. In some cases there is no way to find the available packages, -/// in which case [packages] and [asMap] will throw if used. -/// One such case is if the packages are resolved relative to a -/// `packages/` directory available over HTTP. -abstract class Packages { - /// A [Packages] resolver containing no packages. - /// - /// This constant object is returned by [find] above if no - /// package resolution strategy is found. - static const Packages noPackages = const NoPackages(); - - /// Resolve a package URI into a non-package URI. - /// - /// Translates a `package:` URI, according to the package resolution - /// strategy, into a URI that can be loaded. - /// By default, only `file`, `http` and `https` URIs are returned. - /// Custom `Packages` objects may return other URIs. - /// - /// If resolution fails because a package with the requested package name - /// is not available, the [notFound] function is called. - /// If no `notFound` function is provided, it defaults to throwing an error. - /// - /// The [packageUri] must be a valid package URI. - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}); - - /// Return the names of the available packages. - /// - /// Returns an iterable that allows iterating the names of available packages. - /// - /// Some `Packages` objects are unable to find the package names, - /// and getting `packages` from such a `Packages` object will throw. - Iterable get packages; - - /// Retrieve metadata associated with a package. - /// - /// Metadata have string keys and values, and are looked up by key. - /// - /// Returns `null` if the argument is not a valid package name, - /// or if the package is not one of the packages configured by - /// this packages object, or if the package does not have associated - /// metadata with the provided [key]. - /// - /// Not all `Packages` objects can support metadata. - /// Those will always return `null`. - String packageMetadata(String packageName, String key); - - /// Retrieve metadata associated with a library. - /// - /// If [libraryUri] is a `package:` URI, the returned value - /// is the same that would be returned by [packageMetadata] with - /// the package's name and the same key. - /// - /// If [libraryUri] is not a `package:` URI, and this [Packages] - /// object has a [defaultPackageName], then the [key] is looked - /// up on the default package instead. - /// - /// Otherwise the result is `null`. - String libraryMetadata(Uri libraryUri, String key); - - /// Return the names-to-base-URI mapping of the available packages. - /// - /// Returns a map from package name to a base URI. - /// The [resolve] method will resolve a package URI with a specific package - /// name to a path extending the base URI that this map gives for that - /// package name. - /// - /// Some `Packages` objects are unable to find the package names, - /// and calling `asMap` on such a `Packages` object will throw. - Map asMap(); - - /// The name of the "default package". - /// - /// A default package is a package that *non-package* libraries - /// may be considered part of for some purposes. - /// - /// The value is `null` if there is no default package. - /// Not all implementations of [Packages] supports a default package, - /// and will always have a `null` value for those. - String get defaultPackageName; -} diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart deleted file mode 100644 index 1c35d5b21..000000000 --- a/pkgs/package_config/lib/packages_file.dart +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2015, 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 package_config.packages_file; - -import "package:charcode/ascii.dart"; - -import "src/util.dart" show isValidPackageName; - -/// Parses a `.packages` file into a map from package name to base URI. -/// -/// The [source] is the byte content of a `.packages` file, assumed to be -/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII, -/// so Latin-1 or Windows-1252 encoding will also work fine. -/// -/// If the file content is available as a string, its [String.codeUnits] can -/// be used as the `source` argument of this function. -/// -/// The [baseLocation] is used as a base URI to resolve all relative -/// URI references against. -/// If the content was read from a file, `baseLocation` should be the -/// location of that file. -/// -/// If [allowDefaultPackage] is set to true, an entry with an empty package name -/// is accepted. This entry does not correspond to a package, but instead -/// represents a *default package* which non-package libraries may be considered -/// part of in some cases. The value of that entry must be a valid package name. -/// -/// Returns a simple mapping from package name to package location. -/// If default package is allowed, the map maps the empty string to the default package's name. -Map parse(List source, Uri baseLocation, - {bool allowDefaultPackage = false}) { - int index = 0; - Map result = {}; - while (index < source.length) { - bool isComment = false; - int start = index; - int separatorIndex = -1; - int end = source.length; - int char = source[index++]; - if (char == $cr || char == $lf) { - continue; - } - if (char == $colon) { - if (!allowDefaultPackage) { - throw FormatException("Missing package name", source, index - 1); - } - separatorIndex = index - 1; - } - isComment = char == $hash; - while (index < source.length) { - char = source[index++]; - if (char == $colon && separatorIndex < 0) { - separatorIndex = index - 1; - } else if (char == $cr || char == $lf) { - end = index - 1; - break; - } - } - if (isComment) continue; - if (separatorIndex < 0) { - throw FormatException("No ':' on line", source, index - 1); - } - var packageName = new String.fromCharCodes(source, start, separatorIndex); - if (packageName.isEmpty - ? !allowDefaultPackage - : !isValidPackageName(packageName)) { - throw FormatException("Not a valid package name", packageName, 0); - } - var packageValue = - new String.fromCharCodes(source, separatorIndex + 1, end); - Uri packageLocation; - if (packageName.isEmpty) { - if (!isValidPackageName(packageValue)) { - throw FormatException( - "Default package entry value is not a valid package name"); - } - packageLocation = Uri(path: packageValue); - } else { - packageLocation = baseLocation.resolve(packageValue); - if (!packageLocation.path.endsWith('/')) { - packageLocation = - packageLocation.replace(path: packageLocation.path + "/"); - } - } - if (result.containsKey(packageName)) { - if (packageName.isEmpty) { - throw FormatException( - "More than one default package entry", source, start); - } - throw FormatException("Same package name occured twice", source, start); - } - result[packageName] = packageLocation; - } - return result; -} - -/// Writes the mapping to a [StringSink]. -/// -/// If [comment] is provided, the output will contain this comment -/// with `# ` in front of each line. -/// Lines are defined as ending in line feed (`'\n'`). If the final -/// line of the comment doesn't end in a line feed, one will be added. -/// -/// If [baseUri] is provided, package locations will be made relative -/// to the base URI, if possible, before writing. -/// -/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an -/// empty string mapping to the _default package name_. -/// -/// All the keys of [packageMapping] must be valid package names, -/// and the values must be URIs that do not have the `package:` scheme. -void write(StringSink output, Map packageMapping, - {Uri baseUri, String comment, bool allowDefaultPackage = false}) { - ArgumentError.checkNotNull(allowDefaultPackage, 'allowDefaultPackage'); - - if (baseUri != null && !baseUri.isAbsolute) { - throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); - } - - if (comment != null) { - var lines = comment.split('\n'); - if (lines.last.isEmpty) lines.removeLast(); - for (var commentLine in lines) { - output.write('# '); - output.writeln(commentLine); - } - } else { - output.write("# generated by package:package_config at "); - output.write(new DateTime.now()); - output.writeln(); - } - - packageMapping.forEach((String packageName, Uri uri) { - // If [packageName] is empty then [uri] is the _default package name_. - if (allowDefaultPackage && packageName.isEmpty) { - final defaultPackageName = uri.toString(); - if (!isValidPackageName(defaultPackageName)) { - throw ArgumentError.value( - defaultPackageName, - 'defaultPackageName', - '"$defaultPackageName" is not a valid package name', - ); - } - output.write(':'); - output.write(defaultPackageName); - output.writeln(); - return; - } - // Validate packageName. - if (!isValidPackageName(packageName)) { - throw new ArgumentError('"$packageName" is not a valid package name'); - } - if (uri.scheme == "package") { - throw new ArgumentError.value( - "Package location must not be a package: URI", uri.toString()); - } - output.write(packageName); - output.write(':'); - // If baseUri provided, make uri relative. - if (baseUri != null) { - uri = _relativize(uri, baseUri); - } - if (!uri.path.endsWith('/')) { - uri = uri.replace(path: uri.path + '/'); - } - output.write(uri); - output.writeln(); - }); -} - -/// Attempts to return a relative URI for [uri]. -/// -/// The result URI satisfies `baseUri.resolveUri(result) == uri`, -/// but may be relative. -/// The `baseUri` must be absolute. -Uri _relativize(Uri uri, Uri baseUri) { - assert(baseUri.isAbsolute); - if (uri.hasQuery || uri.hasFragment) { - uri = new Uri( - scheme: uri.scheme, - userInfo: uri.hasAuthority ? uri.userInfo : null, - host: uri.hasAuthority ? uri.host : null, - port: uri.hasAuthority ? uri.port : null, - path: uri.path); - } - - // Already relative. We assume the caller knows what they are doing. - if (!uri.isAbsolute) return uri; - - if (baseUri.scheme != uri.scheme) { - return uri; - } - - // If authority differs, we could remove the scheme, but it's not worth it. - if (uri.hasAuthority != baseUri.hasAuthority) return uri; - if (uri.hasAuthority) { - if (uri.userInfo != baseUri.userInfo || - uri.host.toLowerCase() != baseUri.host.toLowerCase() || - uri.port != baseUri.port) { - return uri; - } - } - - baseUri = baseUri.normalizePath(); - List base = baseUri.pathSegments.toList(); - if (base.isNotEmpty) { - base = new List.from(base)..removeLast(); - } - uri = uri.normalizePath(); - List target = uri.pathSegments.toList(); - if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); - int index = 0; - while (index < base.length && index < target.length) { - if (base[index] != target[index]) { - break; - } - index++; - } - if (index == base.length) { - if (index == target.length) { - return new Uri(path: "./"); - } - return new Uri(path: target.skip(index).join('/')); - } else if (index > 0) { - return new Uri( - path: '../' * (base.length - index) + target.skip(index).join('/')); - } else { - return uri; - } -} diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart new file mode 100644 index 000000000..6b0fc8f0d --- /dev/null +++ b/pkgs/package_config/lib/src/discovery.dart @@ -0,0 +1,132 @@ +// Copyright (c) 2019, 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. + +import "dart:io"; +import 'dart:typed_data'; + +import "package:path/path.dart" as path; + +import "errors.dart"; +import "package_config_impl.dart"; +import "package_config_json.dart"; +import "packages_file.dart" as packages_file; +import "util.dart" show defaultLoader; + +final Uri packageConfigJsonPath = Uri(path: ".dart_tool/package_config.json"); +final Uri dotPackagesPath = Uri(path: ".packages"); +final Uri currentPath = Uri(path: "."); +final Uri parentPath = Uri(path: ".."); + +/// Discover the package configuration for a Dart script. +/// +/// The [baseDirectory] points to the directory of the Dart script. +/// A package resolution strategy is found by going through the following steps, +/// and stopping when something is found. +/// +/// * Check if a `.dart_tool/package_config.json` file exists in the directory. +/// * Check if a `.packages` file exists in the directory. +/// * Repeat these checks for the parent directories until reaching the +/// root directory if [recursive] is true. +/// +/// If any of these tests succeed, a `PackageConfig` class is returned. +/// Returns `null` if no configuration was found. If a configuration +/// is needed, then the caller can supply [PackageConfig.empty]. +Future findPackageConfig( + Directory baseDirectory, bool recursive) async { + var directory = baseDirectory; + if (!directory.isAbsolute) directory = directory.absolute; + if (!await directory.exists()) { + return null; + } + do { + // Check for $cwd/.packages + var packageConfig = await findPackagConfigInDirectory(directory); + if (packageConfig != null) return packageConfig; + if (!recursive) break; + // Check in parent directories. + var parentDirectory = directory.parent; + if (parentDirectory.path == directory.path) break; + directory = parentDirectory; + } while (true); + return null; +} + +/// Similar to [findPackageConfig] but based on a URI. +Future findPackageConfigUri(Uri location, + Future loader(Uri uri) /*?*/, bool recursive) async { + if (location.isScheme("package")) { + throw PackageConfigArgumentError( + location, "location", "Must not be a package: URI"); + } + if (loader == null) { + if (location.isScheme("file")) { + return findPackageConfig( + Directory.fromUri(location.resolveUri(currentPath)), recursive); + } + loader = defaultLoader; + } + if (!location.path.endsWith("/")) location = location.resolveUri(currentPath); + while (true) { + var file = location.resolveUri(packageConfigJsonPath); + var bytes = await loader(file); + if (bytes != null) { + return parsePackageConfigBytes(bytes, file); + } + file = location.resolveUri(dotPackagesPath); + bytes = await loader(file); + if (bytes != null) { + return packages_file.parse(bytes, file); + } + if (!recursive) break; + var parent = location.resolveUri(parentPath); + if (parent == location) break; + location = parent; + } + return null; +} + +/// Finds a `.packages` or `.dart_tool/package_config.json` file in [directory]. +/// +/// Loads the file, if it is there, and returns the resulting [PackageConfig]. +/// Returns `null` if the file isn't there. +/// Throws [FormatException] if a file is there but is not valid. +/// +/// If [extraData] is supplied and the `package_config.json` contains extra +/// entries in the top JSON object, those extra entries are stored into +/// [extraData]. +Future findPackagConfigInDirectory( + Directory directory) async { + var packageConfigFile = await checkForPackageConfigJsonFile(directory); + if (packageConfigFile != null) { + return await readPackageConfigJsonFile(packageConfigFile); + } + packageConfigFile = await checkForDotPackagesFile(directory); + if (packageConfigFile != null) { + return await readDotPackagesFile(packageConfigFile); + } + return null; +} + +Future /*?*/ checkForPackageConfigJsonFile(Directory directory) async { + assert(directory.isAbsolute); + var file = + File(path.join(directory.path, ".dart_tool", "package_config.json")); + if (await file.exists()) return file; + return null; +} + +Future checkForDotPackagesFile(Directory directory) async { + var file = File(path.join(directory.path, ".packages")); + if (await file.exists()) return file; + return null; +} + +Future _loadFile(File file) async { + Uint8List bytes; + try { + return await file.readAsBytes(); + } catch (_) { + return null; + } +} diff --git a/pkgs/package_config/lib/src/errors.dart b/pkgs/package_config/lib/src/errors.dart new file mode 100644 index 000000000..6c31ccea1 --- /dev/null +++ b/pkgs/package_config/lib/src/errors.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2019, 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. + +/// General superclass of most errors and exceptions thrown by this package. +/// +/// Only covers errors thrown while parsing package configuration files. +/// Programming errors and I/O exceptions are not covered. +abstract class PackageConfigError { + PackageConfigError._(); +} + +class PackageConfigArgumentError extends ArgumentError + implements PackageConfigError { + PackageConfigArgumentError(Object /*?*/ value, String name, String message) + : super.value(value, name, message); +} + +class PackageConfigFormatException extends FormatException + implements PackageConfigError { + PackageConfigFormatException(String message, Object /*?*/ value, + [int /*?*/ index]) + : super(message, value, index); +} diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart new file mode 100644 index 000000000..f7b96b8a5 --- /dev/null +++ b/pkgs/package_config/lib/src/package_config.dart @@ -0,0 +1,176 @@ +// Copyright (c) 2019, 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. + +import "package_config_impl.dart"; + +/// A package configuration. +/// +/// Associates configuration data to packages and files in packages. +/// +/// More members may be added to this class in the future, +/// so classes outside of this package must not implement [PackageConfig] +/// or any subclass of it. +abstract class PackageConfig { + /// The largest configuration version currently recognized. + static const int maxVersion = 2; + + /// An empty package configuration. + /// + /// A package configuration with no available packages. + /// Is used as a default value where a package configuration + /// is expected, but none have been specified or found. + static const PackageConfig empty = const SimplePackageConfig.empty(); + + /// Creats a package configuration with the provided available [packages]. + /// + /// The packages must be valid packages (valid package name, valid + /// absolute directory URIs, valid language version, if any), + /// and there must not be two packages with the same name or with + /// overlapping root directories. + /// + /// If supplied, the [extraData] will be available as the + /// [PackageConfig.extraData] of the created configuration. + /// + /// The version of the resulting configuration is always [maxVersion]. + factory PackageConfig(Iterable packages, {dynamic extraData}) => + SimplePackageConfig(maxVersion, packages); + + /// The configuration version number. + /// + /// Currently this is 1 or 2, where + /// * Version one is the `.packages` file format and + /// * Version two is the first `package_config.json` format. + /// + /// Instances of this class supports both, and the version + /// is only useful for detecting which kind of file the configuration + /// was read from. + int get version; + + /// All the available packages of this configuration. + /// + /// No two of these packages have the same name, + /// and no two [Package.root] directories overlap. + Iterable get packages; + + /// Look up a package by name. + /// + /// Returns the [Package] fron [packages] with [packageName] as + /// [Package.name]. Returns `null` if the package is not available in the + /// current configuration. + Package /*?*/ operator [](String packageName); + + /// Provides the associated package for a specific [file] (or directory). + /// + /// Returns a [Package] which contains the [file]'s path, if any. + /// That is, the [Package.rootUri] directory is a parent directory + /// of the [file]'s location. + /// + /// Returns `null` if the file does not belong to any package. + Package /*?*/ packageOf(Uri file); + + /// Resolves a `package:` URI to a non-package URI + /// + /// The [packageUri] must be a valid package URI. That means: + /// * A URI with `package` as scheme, + /// * with no authority part (`package://...`), + /// * with a path starting with a valid package name followed by a slash, and + /// * with no query or fragment part. + /// + /// Throws an [ArgumentError] (which also implements [PackageConfigError]) + /// if the package URI is not valid. + /// + /// Returns `null` if the package name of [packageUri] is not available + /// in this package configuration. + /// Returns the remaining path of the package URI resolved relative to the + /// [Package.packageUriRoot] of the corresponding package. + Uri /*?*/ resolve(Uri packageUri); + + /// The package URI which resolves to [nonPackageUri]. + /// + /// The [nonPackageUri] must not have any query or fragment part, + /// and it must not have `package` as scheme. + /// Throws an [ArgumentError] (which also implements [PackageConfigError]) + /// if the non-package URI is not valid. + /// + /// Returns a package URI which [resolve] will convert to [nonPackageUri], + /// if any such URI exists. Returns `null` if no such package URI exists. + Uri /*?*/ toPackageUri(Uri nonPackageUri); + + /// Extra data associated with the package configuration. + /// + /// The data may be in any format, depending on who introduced it. + /// The standard `packjage_config.json` file storage will only store + /// JSON-like list/map data structures. + dynamic get extraData; +} + +/// Configuration data for a single package. +abstract class Package { + /// Creates a package with the provided properties. + /// + /// The [name] must be a valid package name. + /// The [root] must be an absolute directory URI, meaning an absolute URI + /// with no query or fragment path and a path starting and ending with `/`. + /// The [packageUriRoot], if provided, must be either an absolute + /// directory URI or a relative URI reference which is then resolved + /// relative to [root]. It must then also be a subdirectory of [root], + /// or the same directory. + /// If [languageVersion] is supplied, it must be a valid Dart language + /// version, which means two decimal integer literals separated by a `.`, + /// where the integer literals have no leading zeros unless they are + /// a single zero digit. + /// If [extraData] is supplied, it will be available as the + /// [Package.extraData] of the created package. + factory Package(String name, Uri root, + {Uri /*?*/ packageUriRoot, + String /*?*/ languageVersion, + dynamic extraData}) => + SimplePackage(name, root, packageUriRoot, languageVersion, extraData); + + /// The package-name of the package. + String get name; + + /// The location of the root of the package. + /// + /// Is always an absolute URI with no query or fragment parts, + /// and with a path ending in `/`. + /// + /// All files in the [rootUri] directory are considered + /// part of the package for purposes where that that matters. + Uri get root; + + /// The root of the files available through `package:` URIs. + /// + /// A `package:` URI with [name] as the package name is + /// resolved relative to this location. + /// + /// Is always an absolute URI with no query or fragment part + /// with a path ending in `/`, + /// and with a location which is a subdirectory + /// of the [root], or the same as the [root]. + Uri get packageUriRoot; + + /// The default language version associated with this package. + /// + /// Each package may have a default language version associated, + /// which is the language version used to parse and compile + /// Dart files in the package. + /// A package version is always of the form: + /// + /// * A numeral consisting of one or more decimal digits, + /// with no leading zero unless the entire numeral is a single zero digit. + /// * Followed by a `.` character. + /// * Followed by another numeral of the same form. + /// + /// There is no whitespace allowed around the numerals. + /// Valid version numbers include `2.5`, `3.0`, and `1234.5678`. + String /*?*/ get languageVersion; + + /// Extra data associated with the specific package. + /// + /// The data may be in any format, depending on who introduced it. + /// The standard `packjage_config.json` file storage will only store + /// JSON-like list/map data structures. + dynamic get extraData; +} diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart new file mode 100644 index 000000000..0bbe18f5b --- /dev/null +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -0,0 +1,181 @@ +// Copyright (c) 2019, 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. + +import 'errors.dart'; +import "package_config.dart"; +export "package_config.dart"; +import "util.dart"; + +class SimplePackageConfig implements PackageConfig { + final int version; + final Map _packages; + final dynamic extraData; + + SimplePackageConfig(int version, Iterable packages, [this.extraData]) + : version = _validateVersion(version), + _packages = _validatePackages(packages); + + SimplePackageConfig._( + int version, Iterable packages, this.extraData) + : version = _validateVersion(version), + _packages = {for (var package in packages) package.name: package}; + + /// Creates empty configuration. + /// + /// The empty configuration can be used in cases where no configuration is + /// found, but code expects a non-null configuration. + const SimplePackageConfig.empty() + : version = 1, + _packages = const {}, + extraData = null; + + static int _validateVersion(int version) { + if (version < 0 || version > PackageConfig.maxVersion) { + throw PackageConfigArgumentError(version, "version", + "Must be in the range 1 to ${PackageConfig.maxVersion}"); + } + return version; + } + + static Map _validatePackages(Iterable packages) { + Map result = {}; + for (var package in packages) { + if (package is! SimplePackage) { + // SimplePackage validates these properties. + try { + _validatePackageData(package.name, package.root, + package.packageUriRoot, package.languageVersion); + } catch (e) { + throw PackageConfigArgumentError( + packages, "packages", "Package ${package.name}: ${e.message}"); + } + } + var name = package.name; + if (result.containsKey(name)) { + throw PackageConfigArgumentError( + name, "packages", "Duplicate package name"); + } + result[name] = package; + } + + // Check that no root URI is a prefix of another. + if (result.length > 1) { + // Uris cache their toString, so this is not as bad as it looks. + var rootUris = [...result.values] + ..sort((a, b) => a.root.toString().compareTo(b.root.toString())); + var prev = rootUris[0]; + var prevRoot = prev.root.toString(); + for (int i = 1; i < rootUris.length; i++) { + var next = rootUris[i]; + var nextRoot = next.root.toString(); + // If one string is a prefix of another, + // the former sorts just before the latter. + if (nextRoot.startsWith(prevRoot)) { + throw PackageConfigArgumentError( + packages, + "packages", + "Package ${next.name} root overlaps " + "package ${prev.name} root.\n" + "${prev.name} root: $prevRoot\n" + "${next.name} root: $nextRoot\n"); + } + prev = next; + } + } + return result; + } + + Iterable get packages => _packages.values; + + Package /*?*/ operator [](String packageName) => _packages[packageName]; + + /// Provides the associated package for a specific [file] (or directory). + /// + /// Returns a [Package] which contains the [file]'s path. + /// That is, the [Package.rootUri] directory is a parent directory + /// of the [file]'s location. + /// Returns `null` if the file does not belong to any package. + Package /*?*/ packageOf(Uri file) { + String path = file.toString(); + for (var package in _packages.values) { + var rootPath = package.root.toString(); + if (path.startsWith(rootPath)) return package; + } + return null; + } + + Uri /*?*/ resolve(Uri packageUri) { + String packageName = checkValidPackageUri(packageUri, "packageUri"); + return _packages[packageName]?.packageUriRoot?.resolveUri( + Uri(path: packageUri.path.substring(packageName.length + 1))); + } + + Uri /*?*/ toPackageUri(Uri nonPackageUri) { + if (nonPackageUri.isScheme("package")) { + throw PackageConfigArgumentError( + nonPackageUri, "nonPackageUri", "Must not be a package URI"); + } + if (nonPackageUri.hasQuery || nonPackageUri.hasFragment) { + throw PackageConfigArgumentError(nonPackageUri, "nonPackageUri", + "Must not have query or fragment part"); + } + for (var package in _packages.values) { + var root = package.packageUriRoot; + if (isUriPrefix(root, nonPackageUri)) { + var rest = nonPackageUri.toString().substring(root.toString().length); + return Uri(scheme: "package", path: "${package.name}/$rest"); + } + } + return null; + } +} + +/// Configuration data for a single package. +class SimplePackage implements Package { + final String name; + final Uri root; + final Uri packageUriRoot; + final String /*?*/ languageVersion; + final dynamic extraData; + + SimplePackage._(this.name, this.root, this.packageUriRoot, + this.languageVersion, this.extraData); + + factory SimplePackage(String name, Uri root, Uri packageUriRoot, + String /*?*/ languageVersion, dynamic extraData) { + _validatePackageData(name, root, packageUriRoot, languageVersion); + return SimplePackage._( + name, root, packageUriRoot, languageVersion, extraData); + } +} + +void _validatePackageData( + String name, Uri root, Uri packageUriRoot, String /*?*/ languageVersion) { + if (!isValidPackageName(name)) { + throw PackageConfigArgumentError(name, "name", "Not a valid package name"); + } + if (!isAbsoluteDirectoryUri(root)) { + throw PackageConfigArgumentError( + "$root", + "root", + "Not an absolute URI with no query or fragment " + "with a path ending in /"); + } + if (!isAbsoluteDirectoryUri(packageUriRoot)) { + throw PackageConfigArgumentError( + packageUriRoot, + "packageUriRoot", + "Not an absolute URI with no query or fragment " + "with a path ending in /"); + } + if (!isUriPrefix(root, packageUriRoot)) { + throw PackageConfigArgumentError(packageUriRoot, "packageUriRoot", + "The package URI root is not below the package root"); + } + if (languageVersion != null && + checkValidVersionNumber(languageVersion) >= 0) { + throw PackageConfigArgumentError( + languageVersion, "languageVersion", "Invalid language version format"); + } +} diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart new file mode 100644 index 000000000..8a6014cad --- /dev/null +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -0,0 +1,327 @@ +// Copyright (c) 2019, 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. + +import "dart:convert"; +import "dart:io"; +import "dart:typed_data"; + +import 'package:charcode/ascii.dart'; +import "package:path/path.dart" as path; + +import "discovery.dart" show packageConfigJsonPath; +import "errors.dart"; +import "package_config_impl.dart"; +import "packages_file.dart" as packages_file; +import "util.dart"; + +const String _configVersionKey = "configVersion"; +const String _packagesKey = "packages"; +const List _topNames = [_configVersionKey, _packagesKey]; +const String _nameKey = "name"; +const String _rootUriKey = "rootUri"; +const String _packageUriKey = "packageUri"; +const String _languageVersionKey = "languageVersion"; +const List _packageNames = [ + _nameKey, + _rootUriKey, + _packageUriKey, + _languageVersionKey +]; + +const String _generatedKey = "generated"; +const String _generatorKey = "generator"; +const String _generatorVersionKey = "generatorVersion"; + +/// Reads a package configuration file. +/// +/// Detects whether the [file] is a version one `.packages` file or +/// a version two `package_config.json` file. +/// +/// If the [file] is a `.packages` file, first checks whether there is an +/// adjacent `.dart_tool/package_config.json` file, and if so, +/// reads that instead. +/// +/// The file must exist and be a normal file. +Future readAnyConfigFile(File file) async { + var bytes = await file.readAsBytes(); + int firstChar = firstNonWhitespaceChar(bytes); + if (firstChar != $lbrace) { + // Definitely not a JSON object, probably a .packages. + var alternateFile = File(path.join( + path.dirname(file.path), ".dart_tool", "package_config.json")); + if (!alternateFile.existsSync()) { + return packages_file.parse(bytes, file.uri); + } + file = alternateFile; + bytes = await alternateFile.readAsBytes(); + } + return parsePackageConfigBytes(bytes, file.uri); +} + +/// Like [readAnyConfigFile] but uses a URI and an optional loader. +Future readAnyConfigFileUri( + Uri file, Future loader(Uri uri) /*?*/) async { + if (file.isScheme("package")) { + throw PackageConfigArgumentError( + file, "file", "Must not be a package: URI"); + } + if (loader == null) { + if (file.isScheme("file")) return readAnyConfigFile(File.fromUri(file)); + loader = defaultLoader; + } + var bytes = await loader(file); + if (bytes == null) { + throw PackageConfigArgumentError( + file.toString(), "file", "File cannot be read"); + } + int firstChar = firstNonWhitespaceChar(bytes); + if (firstChar != $lbrace) { + // Definitely not a JSON object, probably a .packages. + var alternateFile = file.resolveUri(packageConfigJsonPath); + var alternateBytes = await loader(alternateFile); + if (alternateBytes == null) { + return packages_file.parse(bytes, file); + } + bytes = alternateBytes; + file = alternateFile; + } + return parsePackageConfigBytes(bytes, file); +} + +Future readPackageConfigJsonFile(File file) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (_) { + return null; + } + return parsePackageConfigBytes(bytes, file.uri); +} + +Future readDotPackagesFile(File file) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (_) { + return null; + } + return packages_file.parse(bytes, file.uri); +} + +PackageConfig parsePackageConfigBytes(Uint8List bytes, Uri file) { + // TODO(lrn): Make this simpler. Maybe parse directly from bytes. + return parsePackageConfigJson(json.fuse(utf8).decode(bytes), file); +} + +/// Creates a [PackageConfig] from a parsed JSON-like object structure. +/// +/// The [json] argument must be a JSON object (`Map`) +/// containing a `"configVersion"` entry with an integer value in the range +/// 1 to [PackageConfig.maxVersion], +/// and with a `"packages"` entry which is a JSON array (`List`) +/// containing JSON objects which each has the following properties: +/// +/// * `"name"`: The package name as a string. +/// * `"rootUri"`: The root of the package as a URI stored as a string. +/// * `"packageUri"`: Optionally the root of for `package:` URI resolution +/// for the package, as a relative URI below the root URI +/// stored as a string. +/// * `"languageVersion"`: Optionally a language version string which is a +/// an integer numeral, a decimal point (`.`) and another integer numeral, +/// where the integer numeral cannot have a sign, and can only have a +/// leading zero if the entire numeral is a single zero. +/// +/// All other properties are stored in [extraData]. +/// +/// The [baseLocation] is used as base URI to resolve the "rootUri" +/// URI referencestring. +PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { + if (!baseLocation.hasScheme || baseLocation.isScheme("package")) { + throw PackageConfigArgumentError(baseLocation.toString(), "baseLocation", + "Must be an absolute non-package: URI"); + } + + if (!baseLocation.path.endsWith("/")) { + baseLocation = baseLocation.resolveUri(Uri(path: ".")); + } + + String typeName() { + if (0 is T) return "int"; + if ("" is T) return "string"; + if (const [] is T) return "array"; + return "object"; + } + + T checkType(dynamic value, String name, [String /*?*/ packageName]) { + if (value is T) return value; + // The only types we are called with are [int], [String], [List] + // and Map. Recognize which to give a better error message. + var message = + "$name${packageName != null ? " of package $packageName" : ""}" + " is not a JSON ${typeName()}"; + throw PackageConfigFormatException(message, value); + } + + Package parsePackage(Map entry) { + String /*?*/ name; + String /*?*/ rootUri; + String /*?*/ packageUri; + String /*?*/ languageVersion; + Map /*?*/ extraData; + entry.forEach((key, value) { + switch (key) { + case _nameKey: + name = checkType(value, _nameKey); + break; + case _rootUriKey: + rootUri = checkType(value, _rootUriKey, name); + break; + case _packageUriKey: + packageUri = checkType(value, _packageUriKey, name); + break; + case _languageVersionKey: + languageVersion = checkType(value, _languageVersionKey, name); + break; + default: + (extraData ??= {})[key] = value; + break; + } + }); + if (name == null) { + throw PackageConfigFormatException("Missing name entry", entry); + } + if (rootUri == null) { + throw PackageConfigFormatException("Missing rootUri entry", entry); + } + Uri root = baseLocation.resolve(rootUri); + Uri /*?*/ packageRoot = root; + if (packageUri != null) packageRoot = root.resolve(packageUri); + try { + return SimplePackage(name, root, packageRoot, languageVersion, extraData); + } on ArgumentError catch (e) { + throw PackageConfigFormatException(e.message, e.invalidValue); + } + } + + var map = checkType>(json, "value"); + Map /*?*/ extraData = null; + List /*?*/ packageList; + int /*?*/ configVersion; + map.forEach((key, value) { + switch (key) { + case _configVersionKey: + configVersion = checkType(value, _configVersionKey); + break; + case _packagesKey: + var packageArray = checkType>(value, _packagesKey); + var packages = []; + for (var package in packageArray) { + packages.add(parsePackage( + checkType>(package, "package entry"))); + } + packageList = packages; + break; + default: + (extraData ??= {})[key] = value; + break; + } + }); + if (configVersion == null) { + throw PackageConfigFormatException("Missing configVersion entry", json); + } + if (packageList == null) + throw PackageConfigFormatException("Missing packages list", json); + try { + return SimplePackageConfig(configVersion, packageList, extraData); + } on ArgumentError catch (e) { + throw PackageConfigFormatException(e.message, e.invalidValue); + } +} + +Future writePackageConfigJson( + PackageConfig config, Directory targetDirectory) async { + // Write .dart_tool/package_config.json first. + var file = File( + path.join(targetDirectory.path, ".dart_tool", "package_config.json")); + var baseUri = file.uri; + var extraData = config.extraData; + var data = { + _configVersionKey: PackageConfig.maxVersion, + _packagesKey: [ + for (var package in config.packages) + { + _nameKey: package.name, + _rootUriKey: relativizeUri(package.root, baseUri), + if (package.root != package.packageUriRoot) + _packageUriKey: relativizeUri(package.packageUriRoot, package.root), + if (package.languageVersion != null) + _languageVersionKey: package.languageVersion, + ...?_extractExtraData(package.extraData, _packageNames), + } + ], + ...?_extractExtraData(config.extraData, _topNames), + }; + + // Write .packages too. + String /*?*/ comment; + if (extraData != null) { + String /*?*/ generator = extraData[_generatorKey]; + if (generator != null) { + String /*?*/ generated = extraData[_generatedKey]; + String /*?*/ generatorVersion = extraData[_generatorVersionKey]; + comment = "Generated by $generator" + "${generatorVersion != null ? " $generatorVersion" : ""}" + "${generated != null ? " on $generated" : ""}."; + } + } + file = File(path.join(targetDirectory.path, ".packages")); + baseUri = file.uri; + var buffer = StringBuffer(); + packages_file.write(buffer, config, baseUri: baseUri, comment: comment); + + await Future.wait([ + file.writeAsString(JsonEncoder.withIndent(" ").convert(data)), + file.writeAsString(buffer.toString()), + ]); +} + +/// If "extraData" is a JSON map, then return it, otherwise return null. +/// +/// If the value contains any of the [reservedNames] for the current context, +/// entries with that name in the extra data are dropped. +Map /*?*/ _extractExtraData( + dynamic data, Iterable reservedNames) { + if (data is Map) { + if (data.isEmpty) return null; + for (var name in reservedNames) { + if (data.containsKey(name)) { + data = { + for (var key in data.keys) + if (!reservedNames.contains(key)) key: data[key] + }; + if (data.isEmpty) return null; + for (var value in data.values) { + if (!_validateJson(value)) return null; + } + } + } + return data; + } + return null; +} + +/// Checks that the object is a valid JSON-like data structure. +bool _validateJson(dynamic object) { + if (object == null || object == true || object == false) return true; + if (object is num || object is String) return true; + if (object is List) { + for (var element in object) if (!_validateJson(element)) return false; + return true; + } + if (object is Map) { + for (var value in object.values) if (!_validateJson(value)) return false; + return true; + } + return false; +} diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart new file mode 100644 index 000000000..ac57b4f15 --- /dev/null +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -0,0 +1,150 @@ +// Copyright (c) 2019, 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. + +import "package_config_impl.dart"; +import "package:charcode/ascii.dart"; + +import "util.dart" show isValidPackageName, relativizeUri; +import "errors.dart"; + +/// Parses a `.packages` file into a [PackageConfig]. +/// +/// The [source] is the byte content of a `.packages` file, assumed to be +/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII, +/// so Latin-1 or Windows-1252 encoding will also work fine. +/// +/// If the file content is available as a string, its [String.codeUnits] can +/// be used as the `source` argument of this function. +/// +/// The [baseLocation] is used as a base URI to resolve all relative +/// URI references against. +/// If the content was read from a file, `baseLocation` should be the +/// location of that file. +/// +/// Returns a simple package configuration where each package's +/// [Package.packageUriRoot] is the same as its [Package.root] +/// and it has no [Package.languageVersion]. +PackageConfig parse(List source, Uri baseLocation) { + if (baseLocation.isScheme("package")) { + throw PackageConfigArgumentError( + baseLocation, "baseLocation", "Must not be a package: URI"); + } + int index = 0; + List packages = []; + Set packageNames = {}; + while (index < source.length) { + bool isComment = false; + int start = index; + int separatorIndex = -1; + int end = source.length; + int char = source[index++]; + if (char == $cr || char == $lf) { + continue; + } + if (char == $colon) { + throw PackageConfigFormatException( + "Missing package name", source, index - 1); + } + isComment = char == $hash; + while (index < source.length) { + char = source[index++]; + if (char == $colon && separatorIndex < 0) { + separatorIndex = index - 1; + } else if (char == $cr || char == $lf) { + end = index - 1; + break; + } + } + if (isComment) continue; + if (separatorIndex < 0) { + throw PackageConfigFormatException("No ':' on line", source, index - 1); + } + var packageName = String.fromCharCodes(source, start, separatorIndex); + if (!isValidPackageName(packageName)) { + throw PackageConfigFormatException( + "Not a valid package name", packageName, 0); + } + var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); + Uri packageLocation = baseLocation.resolve(packageValue); + if (packageLocation.isScheme("package")) { + throw PackageConfigFormatException( + "Package URI as location for package", source, separatorIndex + 1); + } + if (packageLocation.hasQuery || packageLocation.hasFragment) { + throw PackageConfigFormatException( + "Location URI must not have query or fragment", source, start); + } + if (!packageLocation.path.endsWith('/')) { + packageLocation = + packageLocation.replace(path: packageLocation.path + "/"); + } + if (packageNames.contains(packageName)) { + throw PackageConfigFormatException( + "Same package name occured more than once", source, start); + } + packages.add(SimplePackage( + packageName, packageLocation, packageLocation, null, null)); + packageNames.add(packageName); + } + return SimplePackageConfig(1, packages, null); +} + +/// Writes the configuration to a [StringSink]. +/// +/// If [comment] is provided, the output will contain this comment +/// with `# ` in front of each line. +/// Lines are defined as ending in line feed (`'\n'`). If the final +/// line of the comment doesn't end in a line feed, one will be added. +/// +/// If [baseUri] is provided, package locations will be made relative +/// to the base URI, if possible, before writing. +/// +/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an +/// empty string mapping to the _default package name_. +/// +/// All the keys of [packageMapping] must be valid package names, +/// and the values must be URIs that do not have the `package:` scheme. +void write(StringSink output, PackageConfig config, + {Uri baseUri, String comment}) { + if (baseUri != null && !baseUri.isAbsolute) { + throw PackageConfigArgumentError(baseUri, "baseUri", "Must be absolute"); + } + + if (comment != null) { + var lines = comment.split('\n'); + if (lines.last.isEmpty) lines.removeLast(); + for (var commentLine in lines) { + output.write('# '); + output.writeln(commentLine); + } + } else { + output.write("# generated by package:package_config at "); + output.write(DateTime.now()); + output.writeln(); + } + for (var package in config.packages) { + var packageName = package.name; + var uri = package.packageUriRoot; + // Validate packageName. + if (!isValidPackageName(packageName)) { + throw PackageConfigArgumentError( + config, "config", '"$packageName" is not a valid package name'); + } + if (uri.scheme == "package") { + throw PackageConfigArgumentError( + config, "config", "Package location must not be a package URI: $uri"); + } + output.write(packageName); + output.write(':'); + // If baseUri provided, make uri relative. + if (baseUri != null) { + uri = relativizeUri(uri, baseUri); + } + if (!uri.path.endsWith('/')) { + uri = uri.replace(path: uri.path + '/'); + } + output.write(uri); + output.writeln(); + } +} diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart deleted file mode 100644 index 817002f1e..000000000 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Implementations of [Packages] that may be used in either server or browser -/// based applications. For implementations that can only run in the browser, -/// see [package_config.packages_io_impl]. -library package_config.packages_impl; - -import "dart:collection" show UnmodifiableMapView; - -import "../packages.dart"; -import "util.dart" show checkValidPackageUri; - -/// A [Packages] null-object. -class NoPackages implements Packages { - const NoPackages(); - - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - String packageName = checkValidPackageUri(packageUri); - if (notFound != null) return notFound(packageUri); - throw new ArgumentError.value( - packageUri, "packageUri", 'No package named "$packageName"'); - } - - Iterable get packages => new Iterable.empty(); - - Map asMap() => const {}; - - String get defaultPackageName => null; - - String packageMetadata(String packageName, String key) => null; - - String libraryMetadata(Uri libraryUri, String key) => null; -} - -/// Base class for [Packages] implementations. -/// -/// This class implements the [resolve] method in terms of a private -/// member -abstract class PackagesBase implements Packages { - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - packageUri = packageUri.normalizePath(); - String packageName = checkValidPackageUri(packageUri); - Uri packageBase = getBase(packageName); - if (packageBase == null) { - if (notFound != null) return notFound(packageUri); - throw new ArgumentError.value( - packageUri, "packageUri", 'No package named "$packageName"'); - } - String packagePath = packageUri.path.substring(packageName.length + 1); - return packageBase.resolve(packagePath); - } - - /// Find a base location for a package name. - /// - /// Returns `null` if no package exists with that name, and that can be - /// determined. - Uri getBase(String packageName); - - String get defaultPackageName => null; - - String packageMetadata(String packageName, String key) => null; - - String libraryMetadata(Uri libraryUri, String key) => null; -} - -/// A [Packages] implementation based on an existing map. -class MapPackages extends PackagesBase { - final Map _mapping; - MapPackages(this._mapping); - - Uri getBase(String packageName) => - packageName.isEmpty ? null : _mapping[packageName]; - - Iterable get packages => _mapping.keys; - - Map asMap() => new UnmodifiableMapView(_mapping); - - String get defaultPackageName => _mapping[""]?.toString(); - - String packageMetadata(String packageName, String key) { - if (packageName.isEmpty) return null; - Uri uri = _mapping[packageName]; - if (uri == null || !uri.hasFragment) return null; - // This can be optimized, either by caching the map or by - // parsing incrementally instead of parsing the entire fragment. - return Uri.splitQueryString(uri.fragment)[key]; - } - - String libraryMetadata(Uri libraryUri, String key) { - if (libraryUri.isScheme("package")) { - return packageMetadata(libraryUri.pathSegments.first, key); - } - var defaultPackageNameUri = _mapping[""]; - if (defaultPackageNameUri != null) { - return packageMetadata(defaultPackageNameUri.toString(), key); - } - return null; - } -} - -/// A [Packages] implementation based on a remote (e.g., HTTP) directory. -/// -/// There is no way to detect which packages exist short of trying to use -/// them. You can't necessarily check whether a directory exists, -/// except by checking for a know file in the directory. -class NonFilePackagesDirectoryPackages extends PackagesBase { - final Uri _packageBase; - NonFilePackagesDirectoryPackages(this._packageBase); - - Uri getBase(String packageName) => _packageBase.resolve("$packageName/"); - - Error _failListingPackages() { - return new UnsupportedError( - "Cannot list packages for a ${_packageBase.scheme}: " - "based package root"); - } - - Iterable get packages { - throw _failListingPackages(); - } - - Map asMap() { - throw _failListingPackages(); - } -} diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart deleted file mode 100644 index 9eba9ce44..000000000 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Implementations of [Packages] that can only be used in server based -/// applications. -library package_config.packages_io_impl; - -import "dart:collection" show UnmodifiableMapView; -import "dart:io" show Directory; - -import "package:path/path.dart" as path; - -import "packages_impl.dart"; - -/// A [Packages] implementation based on a local directory. -class FilePackagesDirectoryPackages extends PackagesBase { - final Directory _packageDir; - final Map _packageToBaseUriMap = {}; - - FilePackagesDirectoryPackages(this._packageDir); - - Uri getBase(String packageName) { - return _packageToBaseUriMap.putIfAbsent(packageName, () { - return new Uri.file(path.join(_packageDir.path, packageName, '.')); - }); - } - - Iterable _listPackageNames() { - return _packageDir - .listSync() - .where((e) => e is Directory) - .map((e) => path.basename(e.path)); - } - - Iterable get packages => _listPackageNames(); - - Map asMap() { - var result = {}; - for (var packageName in _listPackageNames()) { - result[packageName] = getBase(packageName); - } - return new UnmodifiableMapView(result); - } -} diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index f1e1afd0a..25d7b89e4 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -1,12 +1,17 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, 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. /// Utility methods used by more than one library in the package. library package_config.util; +import 'dart:io'; +import 'dart:typed_data'; + import "package:charcode/ascii.dart"; +import "errors.dart"; + // All ASCII characters that are valid in a package name, with space // for all the invalid ones (including space). const String _validPackageNameCharacters = @@ -15,7 +20,7 @@ const String _validPackageNameCharacters = /// Tests whether something is a valid Dart package name. bool isValidPackageName(String string) { - return _findInvalidCharacter(string) < 0; + return checkPackageName(string) < 0; } /// Check if a string is a valid package name. @@ -26,7 +31,7 @@ bool isValidPackageName(String string) { /// Returns `-1` if the string is valid. /// Otherwise returns the index of the first invalid character, /// or `string.length` if the string contains no non-'.' character. -int _findInvalidCharacter(String string) { +int checkPackageName(String string) { // Becomes non-zero if any non-'.' character is encountered. int nonDot = 0; for (int i = 0; i < string.length; i++) { @@ -40,47 +45,46 @@ int _findInvalidCharacter(String string) { return -1; } -/// Validate that a Uri is a valid package:URI. -String checkValidPackageUri(Uri packageUri) { +/// Validate that a [Uri] is a valid `package:` URI. +String checkValidPackageUri(Uri packageUri, String name) { if (packageUri.scheme != "package") { - throw new ArgumentError.value( - packageUri, "packageUri", "Not a package: URI"); + throw PackageConfigArgumentError(packageUri, name, "Not a package: URI"); } if (packageUri.hasAuthority) { - throw new ArgumentError.value( - packageUri, "packageUri", "Package URIs must not have a host part"); + throw PackageConfigArgumentError( + packageUri, name, "Package URIs must not have a host part"); } if (packageUri.hasQuery) { // A query makes no sense if resolved to a file: URI. - throw new ArgumentError.value( - packageUri, "packageUri", "Package URIs must not have a query part"); + throw PackageConfigArgumentError( + packageUri, name, "Package URIs must not have a query part"); } if (packageUri.hasFragment) { // We could leave the fragment after the URL when resolving, // but it would be odd if "package:foo/foo.dart#1" and // "package:foo/foo.dart#2" were considered different libraries. // Keep the syntax open in case we ever get multiple libraries in one file. - throw new ArgumentError.value( - packageUri, "packageUri", "Package URIs must not have a fragment part"); + throw PackageConfigArgumentError( + packageUri, name, "Package URIs must not have a fragment part"); } if (packageUri.path.startsWith('/')) { - throw new ArgumentError.value( - packageUri, "packageUri", "Package URIs must not start with a '/'"); + throw PackageConfigArgumentError( + packageUri, name, "Package URIs must not start with a '/'"); } int firstSlash = packageUri.path.indexOf('/'); if (firstSlash == -1) { - throw new ArgumentError.value(packageUri, "packageUri", + throw PackageConfigArgumentError(packageUri, name, "Package URIs must start with the package name followed by a '/'"); } String packageName = packageUri.path.substring(0, firstSlash); - int badIndex = _findInvalidCharacter(packageName); + int badIndex = checkPackageName(packageName); if (badIndex >= 0) { if (packageName.isEmpty) { - throw new ArgumentError.value( - packageUri, "packageUri", "Package names mus be non-empty"); + throw PackageConfigArgumentError( + packageUri, name, "Package names mus be non-empty"); } if (badIndex == packageName.length) { - throw new ArgumentError.value(packageUri, "packageUri", + throw PackageConfigArgumentError(packageUri, name, "Package names must contain at least one non-'.' character"); } assert(badIndex < packageName.length); @@ -90,8 +94,211 @@ String checkValidPackageUri(Uri packageUri) { // Printable character. badChar = "'${packageName[badIndex]}' ($badChar)"; } - throw new ArgumentError.value( - packageUri, "packageUri", "Package names must not contain $badChar"); + throw PackageConfigArgumentError( + packageUri, name, "Package names must not contain $badChar"); } return packageName; } + +/// Checks whether [version] is a valid Dart language version string. +/// +/// The format is (as RegExp) `^(0|[1-9]\d+)\.(0|[1-9]\d+)$`. +/// +/// Returns the position of the first invalid character, or -1 if +/// the string is valid. +/// If the string is terminated early, the result is the length of the string. +int checkValidVersionNumber(String version) { + if (version == null) { + return 0; + } + int index = 0; + int dotsSeen = 0; + outer: + for (;;) { + // Check for numeral. + if (index == version.length) return index; + int char = version.codeUnitAt(index++); + int digit = char ^ 0x30; + if (digit != 0) { + if (digit < 9) { + while (index < version.length) { + char = version.codeUnitAt(index++); + digit = char ^ 0x30; + if (digit < 9) continue; + if (char == 0x2e /*.*/) { + if (dotsSeen > 0) return index - 1; + dotsSeen = 1; + continue outer; + } + return index - 1; + } + if (dotsSeen > 0) return -1; + return index; + } + return index - 1; + } + // Leading zero means numeral is over. + if (index >= version.length) { + if (dotsSeen > 0) return -1; + return index; + } + if (dotsSeen > 0) return index; + char = version.codeUnitAt(index++); + if (char != 0x2e /*.*/) return index - 1; + } +} + +/// Checks whether URI is just an absolute directory. +/// +/// * It must have a scheme. +/// * It must not have a query or fragment. +/// * The path must start and end with `/`. +bool isAbsoluteDirectoryUri(Uri uri) { + if (uri.hasQuery) return false; + if (uri.hasFragment) return false; + if (!uri.hasScheme) return false; + var path = uri.path; + if (!path.startsWith("/")) return false; + if (!path.endsWith("/")) return false; + return true; +} + +/// Whether the former URI is a prefix of the latter. +bool isUriPrefix(Uri prefix, Uri path) { + assert(!prefix.hasFragment); + assert(!prefix.hasQuery); + assert(!path.hasQuery); + assert(!path.hasFragment); + assert(prefix.path.endsWith('/')); + return path.toString().startsWith(prefix.toString()); +} + +/// Finds the first non-JSON-whitespace character in a file. +/// +/// Used to heuristically detect whether a file is a JSON file or an .ini file. +int firstNonWhitespaceChar(List bytes) { + for (int i = 0; i < bytes.length; i++) { + var char = bytes[i]; + if (char != 0x20 && char != 0x09 && char != 0x0a && char != 0x0d) { + return char; + } + } + return -1; +} + +/// Attempts to return a relative path-only URI for [uri]. +/// +/// First removes any query or fragment part from [uri]. +/// +/// If [uri] is already relative (has no scheme), it's returned as-is. +/// If that is not desired, the caller can pass `baseUri.resolveUri(uri)` +/// as the [uri] instead. +/// +/// If the [uri] has a scheme or authority part which differs from +/// the [baseUri], or if there is no overlap in the paths of the +/// two URIs at all, the [uri] is returned as-is. +/// +/// Otherwise the result is a path-only URI which satsifies +/// `baseUri.resolveUri(result) == uri`, +/// +/// The `baseUri` must be absolute. +Uri relativizeUri(Uri uri, Uri baseUri) { + assert(baseUri.isAbsolute); + if (uri.hasQuery || uri.hasFragment) { + uri = Uri( + scheme: uri.scheme, + userInfo: uri.hasAuthority ? uri.userInfo : null, + host: uri.hasAuthority ? uri.host : null, + port: uri.hasAuthority ? uri.port : null, + path: uri.path); + } + + // Already relative. We assume the caller knows what they are doing. + if (!uri.isAbsolute) return uri; + + if (baseUri.scheme != uri.scheme) { + return uri; + } + + // If authority differs, we could remove the scheme, but it's not worth it. + if (uri.hasAuthority != baseUri.hasAuthority) return uri; + if (uri.hasAuthority) { + if (uri.userInfo != baseUri.userInfo || + uri.host.toLowerCase() != baseUri.host.toLowerCase() || + uri.port != baseUri.port) { + return uri; + } + } + + baseUri = baseUri.normalizePath(); + List base = [...baseUri.pathSegments]; + if (base.isNotEmpty) base.removeLast(); + uri = uri.normalizePath(); + List target = [...uri.pathSegments]; + if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); + int index = 0; + while (index < base.length && index < target.length) { + if (base[index] != target[index]) { + break; + } + index++; + } + if (index == base.length) { + if (index == target.length) { + return Uri(path: "./"); + } + return Uri(path: target.skip(index).join('/')); + } else if (index > 0) { + var buffer = StringBuffer(); + for (int n = base.length - index; n > 0; --n) { + buffer.write("../"); + } + buffer.writeAll(target.skip(index), "/"); + return Uri(path: buffer.toString()); + } else { + return uri; + } +} + +Future defaultLoader(Uri uri) async { + if (uri.isScheme("file")) { + var file = File.fromUri(uri); + try { + return file.readAsBytes(); + } catch (_) { + return null; + } + } + if (uri.isScheme("http") || uri.isScheme("https")) { + return _httpGet(uri); + } + throw UnsupportedError("Default URI unsupported scheme: $uri"); +} + +Future _httpGet(Uri uri) async { + assert(uri.isScheme("http") || uri.isScheme("https")); + HttpClient client = new HttpClient(); + HttpClientRequest request = await client.getUrl(uri); + HttpClientResponse response = await request.close(); + if (response.statusCode != HttpStatus.ok) { + return null; + } + List> splitContent = await response.toList(); + int totalLength = 0; + if (splitContent.length == 1) { + var part = splitContent[0]; + if (part is Uint8List) { + return part; + } + } + for (var list in splitContent) { + totalLength += list.length; + } + Uint8List result = new Uint8List(totalLength); + int offset = 0; + for (Uint8List contentPart in splitContent) { + result.setRange(offset, offset + contentPart.length, contentPart); + offset += contentPart.length; + } + return result; +} diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 72d299bf2..0cd7ddc52 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,11 +1,11 @@ -name: package_config -version: 1.2.0 -description: Support for working with Package Resolution config files. +name: package_config_2 +version: 2.0.0 +description: Support for working with Package Configuration files. author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=2.0.0-dev <3.0.0' + sdk: '>=2.5.0-dev <3.0.0' dependencies: charcode: ^1.1.0 diff --git a/pkgs/package_config/test/all.dart b/pkgs/package_config/test/all.dart deleted file mode 100644 index 78e6cffd1..000000000 --- a/pkgs/package_config/test/all.dart +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2015, 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. - -import "package:test/test.dart"; - -import "discovery_analysis_test.dart" as discovery_analysis; -import "discovery_test.dart" as discovery; -import "parse_test.dart" as parse; -import "parse_write_test.dart" as parse_write; - -main() { - group("parse:", parse.main); - group("discovery:", discovery.main); - group("discovery-analysis:", discovery_analysis.main); - group("parse/write:", parse_write.main); -} diff --git a/pkgs/package_config/test/discovery_analysis_test.dart b/pkgs/package_config/test/discovery_analysis_test.dart deleted file mode 100644 index e43245468..000000000 --- a/pkgs/package_config/test/discovery_analysis_test.dart +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2015, 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 package_config.discovery_analysis_test; - -import "dart:async"; -import "dart:io"; - -import "package:package_config/discovery_analysis.dart"; -import "package:package_config/packages.dart"; -import "package:path/path.dart" as path; -import "package:test/test.dart"; - -main() { - fileTest("basic", { - ".packages": packagesFile, - "foo": {".packages": packagesFile}, - "bar": { - "packages": {"foo": {}, "bar": {}, "baz": {}} - }, - "baz": {} - }, (Directory directory) { - var dirUri = new Uri.directory(directory.path); - PackageContext ctx = PackageContext.findAll(directory); - PackageContext root = ctx[directory]; - expect(root, same(ctx)); - validatePackagesFile(root.packages, dirUri); - var fooDir = sub(directory, "foo"); - PackageContext foo = ctx[fooDir]; - expect(identical(root, foo), isFalse); - validatePackagesFile(foo.packages, dirUri.resolve("foo/")); - var barDir = sub(directory, "bar"); - PackageContext bar = ctx[sub(directory, "bar")]; - validatePackagesDir(bar.packages, dirUri.resolve("bar/")); - PackageContext barbar = ctx[sub(barDir, "bar")]; - expect(barbar, same(bar)); // inherited. - PackageContext baz = ctx[sub(directory, "baz")]; - expect(baz, same(root)); // inherited. - - var map = ctx.asMap(); - expect(map.keys.map((dir) => dir.path), - unorderedEquals([directory.path, fooDir.path, barDir.path])); - return null; - }); -} - -Directory sub(Directory parent, String dirName) { - return new Directory(path.join(parent.path, dirName)); -} - -const packagesFile = """ -# A comment -foo:file:///dart/packages/foo/ -bar:http://example.com/dart/packages/bar/ -baz:packages/baz/ -"""; - -void validatePackagesFile(Packages resolver, Uri location) { - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); -} - -void validatePackagesDir(Packages resolver, Uri location) { - // Expect three packages: foo, bar and baz - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - if (location.scheme == "file") { - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); - } else { - expect(() => resolver.packages, throwsUnsupportedError); - } -} - -Uri pkg(String packageName, String packagePath) { - var path; - if (packagePath.startsWith('/')) { - path = "$packageName$packagePath"; - } else { - path = "$packageName/$packagePath"; - } - return new Uri(scheme: "package", path: path); -} - -/// Create a directory structure from [description] and run [fileTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void fileTest( - String name, Map description, Future fileTest(Directory directory)) { - group("file-test", () { - Directory tempDir = Directory.systemTemp.createTempSync("file-test"); - setUp(() { - _createFiles(tempDir, description); - }); - tearDown(() { - tempDir.deleteSync(recursive: true); - }); - test(name, () => fileTest(tempDir)); - }); -} - -void _createFiles(Directory target, Map description) { - description.forEach((name, content) { - if (content is Map) { - Directory subDir = new Directory(path.join(target.path, name)); - subDir.createSync(); - _createFiles(subDir, content); - } else { - File file = new File(path.join(target.path, name)); - file.writeAsStringSync(content, flush: true); - } - }); -} diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 282427289..5db24a100 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -1,327 +1,250 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, 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 package_config.discovery_test; -import "dart:async"; import "dart:io"; import "package:test/test.dart"; -import "package:package_config/packages.dart"; -import "package:package_config/discovery.dart"; -import "package:path/path.dart" as path; +import "package:package_config_2/package_config.dart"; + +import "src/util.dart"; const packagesFile = """ # A comment foo:file:///dart/packages/foo/ -bar:http://example.com/dart/packages/bar/ +bar:/dart/packages/bar/ baz:packages/baz/ """; -void validatePackagesFile(Packages resolver, Uri location) { - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +const packageConfigFile = """ +{ + "configVersion": 2, + "packages": [ + { + "name": "foo", + "rootUri": "file:///dart/packages/foo/" + }, + { + "name": "bar", + "rootUri": "/dart/packages/bar/" + }, + { + "name": "baz", + "rootUri": "../packages/baz/" + } + ], + "extra": [42] } +"""; -void validatePackagesDir(Packages resolver, Uri location) { - // Expect three packages: foo, bar and baz +void validatePackagesFile(PackageConfig resolver, Directory directory) { expect(resolver, isNotNull); expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); + equals(Uri.parse("file:///dart/packages/bar/baz/qux"))); expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - if (location.scheme == "file") { - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); - } else { - expect(() => resolver.packages, throwsUnsupportedError); - } -} - -Uri pkg(String packageName, String packagePath) { - var path; - if (packagePath.startsWith('/')) { - path = "$packageName$packagePath"; - } else { - path = "$packageName/$packagePath"; - } - return new Uri(scheme: "package", path: path); + equals(Uri.directory(directory.path).resolve("packages/baz/qux/foo"))); + expect([for (var p in resolver.packages) p.name], + unorderedEquals(["foo", "bar", "baz"])); } main() { - generalTest(".packages", { - ".packages": packagesFile, - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}} - }, (Uri location) async { - Packages resolver; - resolver = await findPackages(location); - validatePackagesFile(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesFile(resolver, location); - var specificDiscovery = (location.scheme == "file") - ? findPackagesFromFile - : findPackagesFromNonFile; - resolver = await specificDiscovery(location); - validatePackagesFile(resolver, location); - resolver = await specificDiscovery(location.resolve("script.dart")); - validatePackagesFile(resolver, location); - }); - - generalTest("packages/", { - "packages": {"foo": {}, "bar": {}, "baz": {}}, - "script.dart": "main(){}" - }, (Uri location) async { - Packages resolver; - bool isFile = (location.scheme == "file"); - resolver = await findPackages(location); - validatePackagesDir(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - var specificDiscovery = - isFile ? findPackagesFromFile : findPackagesFromNonFile; - resolver = await specificDiscovery(location); - validatePackagesDir(resolver, location); - resolver = await specificDiscovery(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - }); - - generalTest("underscore packages", { - "packages": {"_foo": {}} - }, (Uri location) async { - Packages resolver = await findPackages(location); - expect(resolver.resolve(pkg("_foo", "foo.dart")), - equals(location.resolve("packages/_foo/foo.dart"))); - }); - - fileTest(".packages recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} - }, (Uri location) async { - Packages resolver; - resolver = await findPackages(location.resolve("subdir/")); - validatePackagesFile(resolver, location); - resolver = await findPackages(location.resolve("subdir/script.dart")); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromFile(location.resolve("subdir/")); - validatePackagesFile(resolver, location); - resolver = - await findPackagesFromFile(location.resolve("subdir/script.dart")); - validatePackagesFile(resolver, location); - }); + group("findPackages", () { + // Finds package_config.json if there. + fileTest("package_config.json", { + ".packages": "invalid .packages file", + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}}, + ".dart_tool": { + "package_config.json": packageConfigFile, + } + }, (Directory directory) async { + PackageConfig config = await findPackageConfig(directory); + expect(config.version, 2); // Found package_config.json file. + validatePackagesFile(config, directory); + }); - httpTest(".packages not recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} - }, (Uri location) async { - Packages resolver; - var subdir = location.resolve("subdir/"); - resolver = await findPackages(subdir); - validatePackagesDir(resolver, subdir); - resolver = await findPackages(subdir.resolve("script.dart")); - validatePackagesDir(resolver, subdir); - resolver = await findPackagesFromNonFile(subdir); - validatePackagesDir(resolver, subdir); - resolver = await findPackagesFromNonFile(subdir.resolve("script.dart")); - validatePackagesDir(resolver, subdir); - }); + // Finds .packages if no package_config.json. + fileTest(".packages", { + ".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}} + }, (Directory directory) async { + PackageConfig config = await findPackageConfig(directory); + expect(config.version, 1); // Found .packages file. + validatePackagesFile(config, directory); + }); - fileTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { - // A file: location with no .packages or packages returns - // Packages.noPackages. - Packages resolver; - resolver = await findPackages(location); - expect(resolver, same(Packages.noPackages)); - resolver = await findPackages(location.resolve("script.dart")); - expect(resolver, same(Packages.noPackages)); - resolver = findPackagesFromFile(location); - expect(resolver, same(Packages.noPackages)); - resolver = findPackagesFromFile(location.resolve("script.dart")); - expect(resolver, same(Packages.noPackages)); - }); + // Finds package_config.json in super-directory. + fileTest("package_config.json recursive", { + ".packages": packagesFile, + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + "subdir": { + "script.dart": "main(){}", + } + }, (Directory directory) async { + PackageConfig config = + await findPackageConfig(subdir(directory, "subdir/")); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); - httpTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location); - validatePackagesDir(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - }); + // Finds .packages in super-directory. + fileTest(".packages recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Directory directory) async { + PackageConfig config; + config = await findPackageConfig(subdir(directory, "subdir/")); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); - test(".packages w/ loader", () async { - Uri location = Uri.parse("krutch://example.com/path/"); - Future> loader(Uri file) async { - if (file.path.endsWith(".packages")) { - return packagesFile.codeUnits; + // Does not find a packages/ directory, and returns null if nothing found. + fileTest("package directory packages not supported", { + "packages": { + "foo": {}, } - throw "not found"; - } - - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location, loader: loader); - validatePackagesFile(resolver, location); - resolver = - await findPackages(location.resolve("script.dart"), loader: loader); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromNonFile(location, loader: loader); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader: loader); - validatePackagesFile(resolver, location); - }); + }, (Directory directory) async { + PackageConfig config = await findPackageConfig(directory); + expect(config, null); + }); - test("no packages w/ loader", () async { - Uri location = Uri.parse("krutch://example.com/path/"); - Future> loader(Uri file) async { - throw "not found"; - } + fileTest("invalid .packages", { + ".packages": "not a .packages file", + }, (Directory directory) { + expect(() => findPackageConfig(directory), + throwsA(TypeMatcher())); + }); - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location, loader: loader); - validatePackagesDir(resolver, location); - resolver = - await findPackages(location.resolve("script.dart"), loader: loader); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location, loader: loader); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader: loader); - validatePackagesDir(resolver, location); - }); + fileTest("invalid .packages as JSON", { + ".packages": packageConfigFile, + }, (Directory directory) { + expect(() => findPackageConfig(directory), + throwsA(TypeMatcher())); + }); - generalTest("loadPackagesFile", {".packages": packagesFile}, - (Uri directory) async { - Uri file = directory.resolve(".packages"); - Packages resolver = await loadPackagesFile(file); - validatePackagesFile(resolver, file); - }); + fileTest("invalid .packages", { + ".dart_tool": { + "package_config.json": "not a JSON file", + } + }, (Directory directory) { + expect(() => findPackageConfig(directory), + throwsA(TypeMatcher())); + }); - generalTest( - "loadPackagesFile non-default name", {"pheldagriff": packagesFile}, - (Uri directory) async { - Uri file = directory.resolve("pheldagriff"); - Packages resolver = await loadPackagesFile(file); - validatePackagesFile(resolver, file); + fileTest("invalid .packages as INI", { + ".dart_tool": { + "package_config.json": packagesFile, + } + }, (Directory directory) { + expect(() => findPackageConfig(directory), + throwsA(TypeMatcher())); + }); }); - test("loadPackagesFile w/ loader", () async { - Future> loader(Uri uri) async => packagesFile.codeUnits; - Uri file = Uri.parse("krutz://example.com/.packages"); - Packages resolver = await loadPackagesFile(file, loader: loader); - validatePackagesFile(resolver, file); - }); + group("loadPackageConfig", () { + // Load a specific files + group("package_config.json", () { + var files = { + ".packages": packagesFile, + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + }; + fileTest("directly", files, (Directory directory) async { + File file = + dirFile(subdir(directory, ".dart_tool"), "package_config.json"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + fileTest("indirectly through .packages", files, + (Directory directory) async { + File file = dirFile(directory, ".packages"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + }); - generalTest("loadPackagesFile not found", {}, (Uri directory) async { - Uri file = directory.resolve(".packages"); - expect( - loadPackagesFile(file), - throwsA(anyOf(new TypeMatcher(), - new TypeMatcher()))); - }); + fileTest("package_config.json non-default name", { + ".packages": packagesFile, + "subdir": { + "pheldagriff": packageConfigFile, + }, + }, (Directory directory) async { + File file = dirFile(directory, "subdir/pheldagriff"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); - generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, - (Uri directory) async { - Uri file = directory.resolve(".packages"); - expect(loadPackagesFile(file), throwsFormatException); - }); + fileTest("package_config.json named .packages", { + "subdir": { + ".packages": packageConfigFile, + }, + }, (Directory directory) async { + File file = dirFile(directory, "subdir/.packages"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); - generalTest("getPackagesDir", { - "packages": {"foo": {}, "bar": {}, "baz": {}} - }, (Uri directory) async { - Uri packages = directory.resolve("packages/"); - Packages resolver = getPackagesDirectory(packages); - Uri resolved = resolver.resolve(pkg("foo", "flip/flop")); - expect(resolved, packages.resolve("foo/flip/flop")); - }); -} + fileTest(".packages", { + ".packages": packagesFile, + }, (Directory directory) async { + File file = dirFile(directory, ".packages"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); -/// Create a directory structure from [description] and run [fileTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void fileTest(String name, Map description, Future fileTest(Uri directory)) { - group("file-test", () { - Directory tempDir = Directory.systemTemp.createTempSync("file-test"); - setUp(() { - _createFiles(tempDir, description); + fileTest(".packages non-default name", { + "pheldagriff": packagesFile, + }, (Directory directory) async { + File file = dirFile(directory, "pheldagriff"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 1); + validatePackagesFile(config, directory); }); - tearDown(() { - tempDir.deleteSync(recursive: true); + + fileTest("no config found", {}, (Directory directory) { + File file = dirFile(directory, "anyname"); + expect(() => loadPackageConfig(file), + throwsA(TypeMatcher())); }); - test(name, () => fileTest(new Uri.file(path.join(tempDir.path, ".")))); - }); -} -/// HTTP-server the directory structure from [description] and run [htpTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void httpTest(String name, Map description, Future httpTest(Uri directory)) { - group("http-test", () { - var serverSub; - var uri; - setUp(() { - return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) { - uri = new Uri( - scheme: "http", host: "127.0.0.1", port: server.port, path: "/"); - serverSub = server.listen((HttpRequest request) { - // No error handling. - var path = request.uri.path; - if (path.startsWith('/')) path = path.substring(1); - if (path.endsWith('/')) path = path.substring(0, path.length - 1); - var parts = path.split('/'); - dynamic fileOrDir = description; - for (int i = 0; i < parts.length; i++) { - fileOrDir = fileOrDir[parts[i]]; - if (fileOrDir == null) { - request.response.statusCode = 404; - request.response.close(); - return; - } - } - request.response.write(fileOrDir); - request.response.close(); - }); - }); + fileTest("specified file syntax error", { + "anyname": "syntax error", + }, (Directory directory) { + File file = dirFile(directory, "anyname"); + expect(() => loadPackageConfig(file), throwsFormatException); }); - tearDown(() => serverSub.cancel()); - test(name, () => httpTest(uri)); - }); -} -void generalTest(String name, Map description, Future action(Uri location)) { - fileTest(name, description, action); - httpTest(name, description, action); -} + // Find package_config.json in subdir even if initial file syntax error. + fileTest("specified file syntax error", { + "anyname": "syntax error", + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + }, (Directory directory) async { + File file = dirFile(directory, "anyname"); + PackageConfig config = await loadPackageConfig(file); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); -void _createFiles(Directory target, Map description) { - description.forEach((name, content) { - if (content is Map) { - Directory subDir = new Directory(path.join(target.path, name)); - subDir.createSync(); - _createFiles(subDir, content); - } else { - File file = new File(path.join(target.path, name)); - file.writeAsStringSync(content, flush: true); - } + // A file starting with `{` is a package_config.json file. + fileTest("file syntax error with {", { + ".packages": "{syntax error", + }, (Directory directory) { + File file = dirFile(directory, ".packages"); + expect(() => loadPackageConfig(file), throwsFormatException); + }); }); } diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart new file mode 100644 index 000000000..414a43add --- /dev/null +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -0,0 +1,256 @@ +// Copyright (c) 2019, 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 package_config.discovery_test; + +import "dart:io"; +import "package:test/test.dart"; +import "package:package_config_2/package_config.dart"; + +import "src/util.dart"; + +const packagesFile = """ +# A comment +foo:file:///dart/packages/foo/ +bar:/dart/packages/bar/ +baz:packages/baz/ +"""; + +const packageConfigFile = """ +{ + "configVersion": 2, + "packages": [ + { + "name": "foo", + "rootUri": "file:///dart/packages/foo/" + }, + { + "name": "bar", + "rootUri": "/dart/packages/bar/" + }, + { + "name": "baz", + "rootUri": "../packages/baz/" + } + ], + "extra": [42] +} +"""; + +void validatePackagesFile(PackageConfig resolver, Uri directory) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(directory.resolve("/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(directory.resolve("packages/baz/qux/foo"))); + expect([for (var p in resolver.packages) p.name], + unorderedEquals(["foo", "bar", "baz"])); +} + +main() { + group("findPackages", () { + // Finds package_config.json if there. + loaderTest("package_config.json", { + ".packages": "invalid .packages file", + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}}, + ".dart_tool": { + "package_config.json": packageConfigFile, + } + }, (Uri directory, loader) async { + PackageConfig config = + await findPackageConfigUri(directory, loader: loader); + expect(config.version, 2); // Found package_config.json file. + validatePackagesFile(config, directory); + }); + + // Finds .packages if no package_config.json. + loaderTest(".packages", { + ".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}} + }, (Uri directory, loader) async { + PackageConfig config = + await findPackageConfigUri(directory, loader: loader); + expect(config.version, 1); // Found .packages file. + validatePackagesFile(config, directory); + }); + + // Finds package_config.json in super-directory. + loaderTest("package_config.json recursive", { + ".packages": packagesFile, + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + "subdir": { + "script.dart": "main(){}", + } + }, (Uri directory, loader) async { + PackageConfig config = await findPackageConfigUri( + directory.resolve("subdir/"), + loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + + // Finds .packages in super-directory. + loaderTest(".packages recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Uri directory, loader) async { + PackageConfig config; + config = await findPackageConfigUri(directory.resolve("subdir/"), + loader: loader); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); + + // Does not find a packages/ directory, and returns null if nothing found. + loaderTest("package directory packages not supported", { + "packages": { + "foo": {}, + } + }, (Uri directory, loader) async { + PackageConfig config = + await findPackageConfigUri(directory, loader: loader); + expect(config, null); + }); + + loaderTest("invalid .packages", { + ".packages": "not a .packages file", + }, (Uri directory, loader) { + expect(() => findPackageConfigUri(directory, loader: loader), + throwsA(TypeMatcher())); + }); + + loaderTest("invalid .packages as JSON", { + ".packages": packageConfigFile, + }, (Uri directory, loader) { + expect(() => findPackageConfigUri(directory, loader: loader), + throwsA(TypeMatcher())); + }); + + loaderTest("invalid .packages", { + ".dart_tool": { + "package_config.json": "not a JSON file", + } + }, (Uri directory, loader) { + expect(() => findPackageConfigUri(directory, loader: loader), + throwsA(TypeMatcher())); + }); + + loaderTest("invalid .packages as INI", { + ".dart_tool": { + "package_config.json": packagesFile, + } + }, (Uri directory, loader) { + expect(() => findPackageConfigUri(directory, loader: loader), + throwsA(TypeMatcher())); + }); + }); + + group("loadPackageConfig", () { + // Load a specific files + group("package_config.json", () { + var files = { + ".packages": packagesFile, + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + }; + loaderTest("directly", files, (Uri directory, loader) async { + Uri file = directory.resolve(".dart_tool/package_config.json"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + loaderTest("indirectly through .packages", files, + (Uri directory, loader) async { + Uri file = directory.resolve(".packages"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + }); + + loaderTest("package_config.json non-default name", { + ".packages": packagesFile, + "subdir": { + "pheldagriff": packageConfigFile, + }, + }, (Uri directory, loader) async { + Uri file = directory.resolve("subdir/pheldagriff"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + + loaderTest("package_config.json named .packages", { + "subdir": { + ".packages": packageConfigFile, + }, + }, (Uri directory, loader) async { + Uri file = directory.resolve("subdir/.packages"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + + loaderTest(".packages", { + ".packages": packagesFile, + }, (Uri directory, loader) async { + Uri file = directory.resolve(".packages"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); + + loaderTest(".packages non-default name", { + "pheldagriff": packagesFile, + }, (Uri directory, loader) async { + Uri file = directory.resolve("pheldagriff"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); + + loaderTest("no config found", {}, (Uri directory, loader) { + Uri file = directory.resolve("anyname"); + expect(() => loadPackageConfigUri(file, loader: loader), + throwsArgumentError); + }); + + loaderTest("specified file syntax error", { + "anyname": "syntax error", + }, (Uri directory, loader) { + Uri file = directory.resolve("anyname"); + expect(() => loadPackageConfigUri(file, loader: loader), + throwsFormatException); + }); + + // Find package_config.json in subdir even if initial file syntax error. + loaderTest("specified file syntax error", { + "anyname": "syntax error", + ".dart_tool": { + "package_config.json": packageConfigFile, + }, + }, (Uri directory, loader) async { + Uri file = directory.resolve("anyname"); + PackageConfig config = await loadPackageConfigUri(file, loader: loader); + expect(config.version, 2); + validatePackagesFile(config, directory); + }); + + // A file starting with `{` is a package_config.json file. + loaderTest("file syntax error with {", { + ".packages": "{syntax error", + }, (Uri directory, loader) { + Uri file = directory.resolve(".packages"); + expect(() => loadPackageConfigUri(file, loader: loader), + throwsFormatException); + }); + }); +} diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index b9b1bb510..235f49381 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -1,245 +1,312 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, 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 package_config.parse_test; +import "dart:io"; +import "dart:convert"; -import "package:package_config/packages.dart"; -import "package:package_config/packages_file.dart" show parse; -import "package:package_config/src/packages_impl.dart"; import "package:test/test.dart"; -main() { - var base = Uri.parse("file:///one/two/three/packages.map"); - test("empty", () { - var packages = doParse(emptySample, base); - expect(packages.asMap(), isEmpty); - }); - test("comment only", () { - var packages = doParse(commentOnlySample, base); - expect(packages.asMap(), isEmpty); - }); - test("empty lines only", () { - var packages = doParse(emptyLinesSample, base); - expect(packages.asMap(), isEmpty); - }); - - test("empty lines only", () { - var packages = doParse(emptyLinesSample, base); - expect(packages.asMap(), isEmpty); - }); - - test("single", () { - var packages = doParse(singleRelativeSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single no slash", () { - var packages = doParse(singleRelativeSampleNoSlash, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single no newline", () { - var packages = doParse(singleRelativeSampleNoNewline, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single absolute authority", () { - var packages = doParse(singleAbsoluteSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); - }); - - test("single empty path", () { - var packages = doParse(singleEmptyPathSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.replace(path: "${base.path}/bar/baz.dart"))); - }); +import "package:package_config_2/src/packages_file.dart" as packages; +import "package:package_config_2/src/package_config_json.dart"; +import "src/util.dart"; - test("single absolute path", () { - var packages = doParse(singleAbsolutePathSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.replace(path: "/test/bar/baz.dart"))); - }); +void main() { + group(".packages", () { + test("valid", () { + var packagesFile = "# Generated by pub yadda yadda\n" + "foo:file:///foo/lib/\n" + "bar:/bar/lib/\n" + "baz:lib/\n"; + var result = packages.parse( + utf8.encode(packagesFile), Uri.parse("file:///tmp/file.dart")); + expect(result.version, 1); + expect({for (var p in result.packages) p.name}, {"foo", "bar", "baz"}); + expect(result.resolve(pkg("foo", "foo.dart")), + Uri.parse("file:///foo/lib/foo.dart")); + expect(result.resolve(pkg("bar", "bar.dart")), + Uri.parse("file:///bar/lib/bar.dart")); + expect(result.resolve(pkg("baz", "baz.dart")), + Uri.parse("file:///tmp/lib/baz.dart")); - test("multiple", () { - var packages = doParse(multiRelativeSample, base); - expect(packages.packages.toList()..sort(), equals(["bar", "foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), - equals(base.resolve("../test2/").resolve("foo/baz.dart"))); - }); + var foo = result["foo"]; + expect(foo, isNotNull); + expect(foo.root, Uri.parse("file:///foo/lib/")); + expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); + expect(foo.languageVersion, null); + }); - test("dot-dot 1", () { - var packages = doParse(singleRelativeSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); + test("valid empty", () { + var packagesFile = "# Generated by pub yadda yadda\n"; + var result = + packages.parse(utf8.encode(packagesFile), Uri.file("/tmp/file.dart")); + expect(result.version, 1); + expect({for (var p in result.packages) p.name}, {}); + }); - test("all valid chars can be used in URI segment", () { - var packages = doParse(allValidCharsSample, base); - expect(packages.packages.toList(), equals([allValidChars])); - expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); + group("invalid", () { + var baseFile = Uri.file("/tmp/file.dart"); + testThrows(String name, String content) { + test(name, () { + expect(() => packages.parse(utf8.encode(content), baseFile), + throwsA(TypeMatcher())); + }); + } - test("no invalid chars accepted", () { - var map = {}; - for (int i = 0; i < allValidChars.length; i++) { - map[allValidChars.codeUnitAt(i)] = true; - } - for (int i = 0; i <= 255; i++) { - if (map[i] == true) continue; - var char = new String.fromCharCode(i); - expect(() => doParse("x${char}x:x", null), - anyOf(throwsNoSuchMethodError, throwsFormatException)); - } + testThrows("repeated package name", "foo:lib/\nfoo:lib\n"); + testThrows("no colon", "foo\n"); + testThrows("empty package name", ":lib/\n"); + testThrows("dot only package name", ".:lib/\n"); + testThrows("dot only package name", "..:lib/\n"); + testThrows("invalid package name character", "f\\o:lib/\n"); + testThrows("package URI", "foo:package:bar/lib/"); + testThrows("location with query", "f\\o:lib/?\n"); + testThrows("location with fragment", "f\\o:lib/#\n"); + }); }); - test("no escapes", () { - expect(() => doParse("x%41x:x", base), throwsFormatException); - }); + group("package_config.json", () { + test("valid", () { + var packageConfigFile = """ + { + "configVersion": 2, + "packages": [ + { + "name": "foo", + "rootUri": "file:///foo/", + "packageUri": "lib/", + "languageVersion": "2.5", + "nonstandard": true + }, + { + "name": "bar", + "rootUri": "/bar/", + "packageUri": "lib/", + "languageVersion": "100.100" + }, + { + "name": "baz", + "rootUri": "../", + "packageUri": "lib/" + } + ], + "generator": "pub", + "other": [42] + } + """; + var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), + Uri.parse("file:///tmp/.dart_tool/file.dart")); + expect(config.version, 2); + expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); - test("same name twice", () { - expect( - () => doParse(singleRelativeSample * 2, base), throwsFormatException); - }); + expect(config.resolve(pkg("foo", "foo.dart")), + Uri.parse("file:///foo/lib/foo.dart")); + expect(config.resolve(pkg("bar", "bar.dart")), + Uri.parse("file:///bar/lib/bar.dart")); + expect(config.resolve(pkg("baz", "baz.dart")), + Uri.parse("file:///tmp/lib/baz.dart")); - test("disallow default package", () { - expect(() => doParse(":foo", base, allowDefaultPackage: false), - throwsFormatException); - }); + var foo = config["foo"]; + expect(foo, isNotNull); + expect(foo.root, Uri.parse("file:///foo/")); + expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); + expect(foo.languageVersion, "2.5"); + expect(foo.extraData, {"nonstandard": true}); - test("allow default package", () { - var packages = doParse(":foo", base, allowDefaultPackage: true); - expect(packages.defaultPackageName, "foo"); - }); + var bar = config["bar"]; + expect(bar, isNotNull); + expect(bar.root, Uri.parse("file:///bar/")); + expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/")); + expect(bar.languageVersion, "100.100"); + expect(bar.extraData, null); - test("allow default package name with dot", () { - var packages = doParse(":foo.bar", base, allowDefaultPackage: true); - expect(packages.defaultPackageName, "foo.bar"); - }); + var baz = config["baz"]; + expect(baz, isNotNull); + expect(baz.root, Uri.parse("file:///tmp/")); + expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/")); + expect(baz.languageVersion, null); - test("not two default packages", () { - expect(() => doParse(":foo\n:bar", base, allowDefaultPackage: true), - throwsFormatException); - }); + expect(config.extraData, { + "generator": "pub", + "other": [42] + }); + }); - test("default package invalid package name", () { - // Not a valid *package name*. - expect(() => doParse(":foo/bar", base, allowDefaultPackage: true), - throwsFormatException); - }); + test("valid other order", () { + // The ordering in the file is not important. + var packageConfigFile = """ + { + "generator": "pub", + "other": [42], + "packages": [ + { + "languageVersion": "2.5", + "packageUri": "lib/", + "rootUri": "file:///foo/", + "name": "foo" + }, + { + "packageUri": "lib/", + "languageVersion": "100.100", + "rootUri": "/bar/", + "name": "bar" + }, + { + "packageUri": "lib/", + "name": "baz", + "rootUri": "../" + } + ], + "configVersion": 2 + } + """; + var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), + Uri.parse("file:///tmp/.dart_tool/file.dart")); + expect(config.version, 2); + expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); - group("metadata", () { - var packages = doParse( - ":foo\n" - "foo:foo#metafoo=1\n" - "bar:bar#metabar=2\n" - "baz:baz\n" - "qux:qux#metaqux1=3&metaqux2=4\n", - base, - allowDefaultPackage: true); - test("non-existing", () { - // non-package name. - expect(packages.packageMetadata("///", "f"), null); - expect(packages.packageMetadata("", "f"), null); - // unconfigured package name. - expect(packages.packageMetadata("absent", "f"), null); - // package name without that metadata - expect(packages.packageMetadata("foo", "notfoo"), null); - }); - test("lookup", () { - expect(packages.packageMetadata("foo", "metafoo"), "1"); - expect(packages.packageMetadata("bar", "metabar"), "2"); - expect(packages.packageMetadata("qux", "metaqux1"), "3"); - expect(packages.packageMetadata("qux", "metaqux2"), "4"); + expect(config.resolve(pkg("foo", "foo.dart")), + Uri.parse("file:///foo/lib/foo.dart")); + expect(config.resolve(pkg("bar", "bar.dart")), + Uri.parse("file:///bar/lib/bar.dart")); + expect(config.resolve(pkg("baz", "baz.dart")), + Uri.parse("file:///tmp/lib/baz.dart")); + expect(config.extraData, { + "generator": "pub", + "other": [42] + }); }); - test("by library URI", () { - expect( - packages.libraryMetadata( - Uri.parse("package:foo/index.dart"), "metafoo"), - "1"); - expect( - packages.libraryMetadata( - Uri.parse("package:bar/index.dart"), "metabar"), - "2"); - expect( - packages.libraryMetadata( - Uri.parse("package:qux/index.dart"), "metaqux1"), - "3"); - expect( - packages.libraryMetadata( - Uri.parse("package:qux/index.dart"), "metaqux2"), - "4"); + + // Check that a few minimal configurations are valid. + // These form the basis of invalid tests below. + var cfg = '"configVersion":2'; + var pkgs = '"packages":[]'; + var name = '"name":"foo"'; + var root = '"rootUri":"/foo/"'; + test("minimal", () { + var config = parsePackageConfigBytes(utf8.encode("{$cfg,$pkgs}"), + Uri.parse("file:///tmp/.dart_tool/file.dart")); + expect(config.version, 2); + expect(config.packages, isEmpty); }); - test("by default package", () { - expect( - packages.libraryMetadata( - Uri.parse("file:///whatever.dart"), "metafoo"), - "1"); + test("minimal package", () { + // A package must have a name and a rootUri, the remaining properties + // are optional. + var config = parsePackageConfigBytes( + utf8.encode('{$cfg,"packages":[{$name,$root}]}'), + Uri.parse("file:///tmp/.dart_tool/file.dart")); + expect(config.version, 2); + expect(config.packages.first.name, "foo"); }); - }); - for (String invalidSample in invalid) { - test("invalid '$invalidSample'", () { - var result; - try { - result = doParse(invalidSample, base); - } on FormatException { - // expected - return; + group("invalid", () { + testThrows(String name, String source) { + test(name, () { + expect( + () => parsePackageConfigBytes(utf8.encode(source), + Uri.parse("file:///tmp/.dart_tool/file.dart")), + throwsA(TypeMatcher())); + }); } - fail("Resolved to $result"); - }); - } -} -Packages doParse(String sample, Uri baseUri, - {bool allowDefaultPackage = false}) { - Map map = parse(sample.codeUnits, baseUri, - allowDefaultPackage: allowDefaultPackage); - return new MapPackages(map); -} + testThrows("comment", '# comment\n {$cfg,$pkgs}'); + testThrows(".packages file", 'foo:/foo\n'); + testThrows("no configVersion", '{$pkgs}'); + testThrows("no packages", '{$cfg}'); + group("config version:", () { + testThrows("null", '{"configVersion":null,$pkgs}'); + testThrows("string", '{"configVersion":"2",$pkgs}'); + testThrows("array", '{"configVersion":[2],$pkgs}'); + }); + group("packages:", () { + testThrows("null", '{$cfg,"packages":null}'); + testThrows("string", '{$cfg,"packages":"foo"}'); + testThrows("object", '{$cfg,"packages":{}}'); + }); + group("packages entry:", () { + testThrows("null", '{$cfg,"packages":[null]}'); + testThrows("string", '{$cfg,"packages":["foo"]}'); + testThrows("array", '{$cfg,"packages":[[]]}'); + }); + group("package", () { + testThrows("no name", '{$cfg,"packages":[{$root}]}'); + group("name:", () { + testThrows("null", '{$cfg,"packages":[{"name":null,$root}]}'); + testThrows("num", '{$cfg,"packages":[{"name":1,$root}]}'); + testThrows("object", '{$cfg,"packages":[{"name":{},$root}]}'); + testThrows("empty", '{$cfg,"packages":[{"name":"",$root}]}'); + testThrows("one-dot", '{$cfg,"packages":[{"name":".",$root}]}'); + testThrows("two-dot", '{$cfg,"packages":[{"name":"..",$root}]}'); + testThrows( + "invalid char '\\'", '{$cfg,"packages":[{"name":"\\",$root}]}'); + testThrows( + "invalid char ':'", '{$cfg,"packages":[{"name":":",$root}]}'); + testThrows( + "invalid char ' '", '{$cfg,"packages":[{"name":" ",$root}]}'); + }); -// Valid samples. -var emptySample = ""; -var commentOnlySample = "# comment only\n"; -var emptyLinesSample = "\n\n\r\n"; -var singleRelativeSample = "foo:../test/\n"; -var singleRelativeSampleNoSlash = "foo:../test\n"; -var singleRelativeSampleNoNewline = "foo:../test/"; -var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; -var singleEmptyPathSample = "foo:\n"; -var singleAbsolutePathSample = "foo:/test/\n"; -var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; -// All valid path segment characters in an URI. -var allValidChars = r"!$&'()*+,-.0123456789;=" - r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; - -var allValidCharsSample = "${allValidChars}:../test/\n"; - -// Invalid samples. -var invalid = [ - ":baz.dart", // empty. - "foobar=baz.dart", // no colon (but an equals, which is not the same) - ".:../test/", // dot segment - "..:../test/", // dot-dot segment - "...:../test/", // dot-dot-dot segment - "foo/bar:../test/", // slash in name - "/foo:../test/", // slash at start of name - "?:../test/", // invalid characters. - "[:../test/", // invalid characters. - "x#:../test/", // invalid characters. -]; + testThrows("no root", '{$cfg,"packages":[{$name}]}'); + group("root:", () { + testThrows("null", '{$cfg,"packages":[{$name,"rootUri":null}]}'); + testThrows("num", '{$cfg,"packages":[{$name,"rootUri":1}]}'); + testThrows("object", '{$cfg,"packages":[{$name,"rootUri":{}}]}'); + testThrows("fragment", '{$cfg,"packages":[{$name,"rootUri":"x/#"}]}'); + testThrows("query", '{$cfg,"packages":[{$name,"rootUri":"x/?"}]}'); + testThrows("package-URI", + '{$cfg,"packages":[{$name,"rootUri":"package:x/x/"}]}'); + }); + group("package-URI root:", () { + testThrows( + "null", '{$cfg,"packages":[{$name,$root,"packageUri":null}]}'); + testThrows("num", '{$cfg,"packages":[{$name,$root,"packageUri":1}]}'); + testThrows( + "object", '{$cfg,"packages":[{$name,$root,"packageUri":{}}]}'); + testThrows("fragment", + '{$cfg,"packages":[{$name,$root,"packageUri":"x/#"}]}'); + testThrows( + "query", '{$cfg,"packages":[{$name,$root,"packageUri":"x/?"}]}'); + testThrows("package: URI", + '{$cfg,"packages":[{$name,$root,"packageUri":"package:x/x/"}]}'); + testThrows("not inside root", + '{$cfg,"packages":[{$name,$root,"packageUri":"../other/"}]}'); + }); + group("language version", () { + testThrows("null", + '{$cfg,"packages":[{$name,$root,"languageVersion":null}]}'); + testThrows( + "num", '{$cfg,"packages":[{$name,$root,"languageVersion":1}]}'); + testThrows("object", + '{$cfg,"packages":[{$name,$root,"languageVersion":{}}]}'); + testThrows("empty", + '{$cfg,"packages":[{$name,$root,"languageVersion":""}]}'); + testThrows("non number.number", + '{$cfg,"packages":[{$name,$root,"languageVersion":"x.1"}]}'); + testThrows("number.non number", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1.x"}]}'); + testThrows("non number", + '{$cfg,"packages":[{$name,$root,"languageVersion":"x"}]}'); + testThrows("one number", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1"}]}'); + testThrows("three numbers", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1.2.3"}]}'); + testThrows("leading zero first", + '{$cfg,"packages":[{$name,$root,"languageVersion":"01.1"}]}'); + testThrows("leading zero second", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1.01"}]}'); + testThrows("trailing-", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1.1-1"}]}'); + testThrows("trailing+", + '{$cfg,"packages":[{$name,$root,"languageVersion":"1.1+1"}]}'); + }); + }); + testThrows("duplicate package name", + '{$cfg,"packages":[{$name,$root},{$name,"rootUri":"/other/"}]}'); + testThrows("same roots", + '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); + testThrows( + "overlapping roots", + '{$cfg,"packages":[{$name,$root},' + '{"name":"bar","rootUri":"/foo/sub/"}]}'); + }); + }); +} diff --git a/pkgs/package_config/test/parse_write_test.dart b/pkgs/package_config/test/parse_write_test.dart deleted file mode 100644 index 415b479e9..000000000 --- a/pkgs/package_config/test/parse_write_test.dart +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2015, 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 package_config.parse_write_test; - -import "dart:convert" show utf8; -import "package:package_config/packages_file.dart"; -import "package:test/test.dart"; - -main() { - testBase(baseDirString) { - var baseDir = Uri.parse(baseDirString); - group("${baseDir.scheme} base", () { - Uri packagesFile = baseDir.resolve(".packages"); - - roundTripTest(String name, Map map) { - group(name, () { - test("write with no baseUri", () { - var content = writeToString(map).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with base directory", () { - var content = writeToString(map, baseUri: baseDir).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with base .packages file", () { - var content = writeToString(map, baseUri: packagesFile).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with defaultPackageName", () { - var content = writeToString( - {'': Uri.parse('my_pkg')}..addAll(map), - allowDefaultPackage: true, - ).codeUnits; - var resultMap = parse( - content, - packagesFile, - allowDefaultPackage: true, - ); - expect(resultMap[''].toString(), 'my_pkg'); - expect( - resultMap, - {'': Uri.parse('my_pkg')}..addAll(map), - ); - }); - - test("write with defaultPackageName (utf8)", () { - var content = utf8.encode(writeToString( - {'': Uri.parse('my_pkg')}..addAll(map), - allowDefaultPackage: true, - )); - var resultMap = parse( - content, - packagesFile, - allowDefaultPackage: true, - ); - expect(resultMap[''].toString(), 'my_pkg'); - expect( - resultMap, - {'': Uri.parse('my_pkg')}..addAll(map), - ); - }); - }); - } - - var lowerDir = baseDir.resolve("path3/path4/"); - var higherDir = baseDir.resolve("../"); - var parallelDir = baseDir.resolve("../path3/"); - var rootDir = baseDir.resolve("/"); - var fileDir = Uri.parse("file:///path1/part2/"); - var httpDir = Uri.parse("http://example.com/path1/path2/"); - var otherDir = Uri.parse("other:/path1/path2/"); - - roundTripTest("empty", {}); - roundTripTest("lower directory", {"foo": lowerDir}); - roundTripTest("higher directory", {"foo": higherDir}); - roundTripTest("parallel directory", {"foo": parallelDir}); - roundTripTest("same directory", {"foo": baseDir}); - roundTripTest("root directory", {"foo": rootDir}); - roundTripTest("file directory", {"foo": fileDir}); - roundTripTest("http directory", {"foo": httpDir}); - roundTripTest("other scheme directory", {"foo": otherDir}); - roundTripTest("multiple same-type directories", - {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); - roundTripTest("multiple scheme directories", - {"foo": fileDir, "bar": httpDir, "baz": otherDir}); - roundTripTest("multiple scheme directories and mutliple same type", { - "foo": fileDir, - "bar": httpDir, - "baz": otherDir, - "qux": lowerDir, - "hip": higherDir, - "dep": parallelDir - }); - }); - } - - testBase("file:///base1/base2/"); - testBase("http://example.com/base1/base2/"); - testBase("other:/base1/base2/"); - - // Check that writing adds the comment. - test("write preserves comment", () { - var comment = "comment line 1\ncomment line 2\ncomment line 3"; - var result = writeToString({}, comment: comment); - // Comment with "# " before each line and "\n" after last. - var expectedComment = - "# comment line 1\n# comment line 2\n# comment line 3\n"; - expect(result, startsWith(expectedComment)); - }); -} - -String writeToString( - Map map, { - Uri baseUri, - String comment, - bool allowDefaultPackage = false, -}) { - var buffer = new StringBuffer(); - write(buffer, map, - baseUri: baseUri, - comment: comment, - allowDefaultPackage: allowDefaultPackage); - return buffer.toString(); -} diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart new file mode 100644 index 000000000..ec4e5e8bc --- /dev/null +++ b/pkgs/package_config/test/src/util.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2019, 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. + +import 'dart:convert'; +import "dart:io"; +import 'dart:typed_data'; + +import "package:path/path.dart" as path; +import "package:test/test.dart"; + +/// Creates a directory structure from [description] and runs [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a subdirectory, otherwise it's a file and the value is the content +/// as a string. +/// Introduces a group to hold the [setUp]/[tearDown] logic. +void fileTest(String name, Map description, + void fileTest(Directory directory)) { + group("file-test", () { + Directory tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(tempDir)); + }); +} + +/// Creates a set of files under a new temporary directory. +/// Returns the temporary directory. +/// +/// The [description] is a map from file names to content. +/// If the content is again a map, it represents a subdirectory +/// with the content as description. +/// Otherwise the content should be a string, +/// which is written to the file as UTF-8. +Directory createTestFiles(Map description) { + var target = Directory.systemTemp.createTempSync("pkgcfgtest"); + _createFiles(target, description); + return target; +} + +// Creates temporary files in the target directory. +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + var entryName = path.join(target.path, "$name"); + if (content is Map) { + _createFiles(Directory(entryName)..createSync(), content); + } else { + File(entryName).writeAsStringSync(content, flush: true); + } + }); +} + +/// Creates a [Directory] for a subdirectory of [parent]. +Directory subdir(Directory parent, String dirName) => + Directory(path.joinAll([parent.path, ...dirName.split("/")])); + +/// Creates a [File] for an entry in the [directory] directory. +File dirFile(Directory directory, String fileName) => + File(path.join(directory.path, fileName)); + +/// Creates a package: URI. +Uri pkg(String packageName, String packagePath) { + var path = + "$packageName${packagePath.startsWith('/') ? "" : "/"}$packagePath"; + return new Uri(scheme: "package", path: path); +} + +// Remove if not used. +String configFromPackages(List> packages) => """ +{ + "configVersion": 2, + "packages": [ +${packages.map((nu) => """ + { + "name": "${nu[0]}", + "rootUri": "${nu[1]}" + }""").join(",\n")} + ] +} +"""; + +/// Mimics a directory structure of [description] and runs [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a subdirectory, otherwise it's a file and the value is the content +/// as a string. +void loaderTest(String name, Map description, + void loaderTest(Uri root, Future loader(Uri uri))) { + Uri root = Uri(scheme: "test", path: "/"); + Future loader(Uri uri) async { + var path = uri.path; + if (!uri.isScheme("test") || !path.startsWith("/")) return null; + var parts = path.split("/"); + dynamic value = description; + for (int i = 1; i < parts.length; i++) { + if (value is! Map) return null; + value = value[parts[i]]; + } + if (value is String) return utf8.encode(value); + return null; + } + + test(name, () => loaderTest(root, loader)); +} From 7620e6b877ec39ebc0afb7ad1d3d9dea4ab635c5 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 27 Jan 2020 12:50:59 +0100 Subject: [PATCH 128/281] Further tweaks on the API. (dart-lang/package_config#57) * Allow nested packages. --- pkgs/package_config/lib/package_config.dart | 38 +-- pkgs/package_config/lib/src/discovery.dart | 16 +- .../lib/src/package_config_impl.dart | 251 ++++++++++++++---- .../lib/src/package_config_json.dart | 56 ++-- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 7 + .../test/discovery_uri_test.dart | 1 - pkgs/package_config/test/parse_test.dart | 47 +++- 8 files changed, 309 insertions(+), 109 deletions(-) diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 4d6f346d7..77e8d61bf 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -23,10 +23,16 @@ export "src/errors.dart" show PackageConfigError; /// It is considered a `package_config.json` file if its first character /// is a `{`. /// -/// If the file is a `.packages` file, also checks if there is a -/// `.dart_tool/package_config.json` file next to the original file, +/// If the file is a `.packages` file and [preferNewest] is true, the default, +/// also checks if there is a `.dart_tool/package_config.json` file next to the original file, /// and if so, loads that instead. -Future loadPackageConfig(File file) => readAnyConfigFile(file); +/// If [preferNewest] is set to false, a directly specified `.packages` file +/// is loaded even if there is an available `package_config.json` file. +/// The caller can determine this from the [PackageConfig.version] +/// being 1 and look for a `package_config.json` file themselves. +Future loadPackageConfig(File file, + {bool preferNewest = true}) => + readAnyConfigFile(file, preferNewest); /// Reads a specific package configuration URI. /// @@ -36,19 +42,24 @@ Future loadPackageConfig(File file) => readAnyConfigFile(file); /// It is considered a `package_config.json` file if its first /// non-whitespace character is a `{`. /// -/// If the file is a `.packages` file, first checks if there is a -/// `.dart_tool/package_config.json` file next to the original file, -/// and if so, loads that instead. +/// If [preferNewest] is true, the default, and the file is a `.packages` file, +/// first checks if there is a `.dart_tool/package_config.json` file +/// next to the original file, and if so, loads that instead. /// The [file] *must not* be a `package:` URI. +/// If [preferNewest] is set to false, a directly specified `.packages` file +/// is loaded even if there is an available `package_config.json` file. +/// The caller can determine this from the [PackageConfig.version] +/// being 1 and look for a `package_config.json` file themselves. /// /// If [loader] is provided, URIs are loaded using that function. /// The future returned by the loader must complete with a [Uint8List] -/// containing the entire file content, +/// containing the entire file content encoded as UTF-8, /// or with `null` if the file does not exist. /// The loader may throw at its own discretion, for situations where /// it determines that an error might be need user attention, /// but it is always allowed to return `null`. /// This function makes no attempt to catch such errors. +/// As such, it may throw any error that [loader] throws. /// /// If no [loader] is supplied, a default loader is used which /// only accepts `file:`, `http:` and `https:` URIs, @@ -58,8 +69,9 @@ Future loadPackageConfig(File file) => readAnyConfigFile(file); /// As such, it does not distinguish between a file not existing, /// and it being temporarily locked or unreachable. Future loadPackageConfigUri(Uri file, - {Future loader(Uri uri) /*?*/}) => - readAnyConfigFileUri(file, loader); + {Future loader(Uri uri) /*?*/, + bool preferNewest = true}) => + readAnyConfigFileUri(file, loader, preferNewest); /// Finds a package configuration relative to [directory]. /// @@ -123,14 +135,6 @@ Future findPackageConfigUri(Uri location, /// If the `.dart_tool/` directory does not exist, it is created. /// If it cannot be created, this operation fails. /// -/// If [extraData] contains any entries, they are added to the JSON -/// written to the `package_config.json` file. Entries with the names -/// `"configVersion"` or `"packages"` are ignored, all other entries -/// are added verbatim. -/// This is intended for, e.g., the -/// `"generator"`, `"generated"` and `"generatorVersion"` -/// properties. -/// /// Also writes a `.packages` file in [directory]. /// This will stop happening eventually as the `.packages` file becomes /// discontinued. diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 6b0fc8f0d..5ad6ac54e 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -5,7 +5,7 @@ import "dart:io"; import 'dart:typed_data'; -import "package:path/path.dart" as path; +import "package:path/path.dart" as p; import "errors.dart"; import "package_config_impl.dart"; @@ -110,23 +110,13 @@ Future findPackagConfigInDirectory( Future /*?*/ checkForPackageConfigJsonFile(Directory directory) async { assert(directory.isAbsolute); - var file = - File(path.join(directory.path, ".dart_tool", "package_config.json")); + var file = File(p.join(directory.path, ".dart_tool", "package_config.json")); if (await file.exists()) return file; return null; } Future checkForDotPackagesFile(Directory directory) async { - var file = File(path.join(directory.path, ".packages")); + var file = File(p.join(directory.path, ".packages")); if (await file.exists()) return file; return null; } - -Future _loadFile(File file) async { - Uint8List bytes; - try { - return await file.readAsBytes(); - } catch (_) { - return null; - } -} diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 0bbe18f5b..62579610c 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -4,22 +4,26 @@ import 'errors.dart'; import "package_config.dart"; -export "package_config.dart"; import "util.dart"; +export "package_config.dart"; + class SimplePackageConfig implements PackageConfig { final int version; final Map _packages; + final PackageTree _packageTree; final dynamic extraData; - SimplePackageConfig(int version, Iterable packages, [this.extraData]) - : version = _validateVersion(version), - _packages = _validatePackages(packages); + SimplePackageConfig(int version, Iterable packages, + [dynamic extraData]) + : this._(_validateVersion(version), packages, + [...packages]..sort(_compareRoot), extraData); - SimplePackageConfig._( - int version, Iterable packages, this.extraData) - : version = _validateVersion(version), - _packages = {for (var package in packages) package.name: package}; + /// Expects a list of [packages] sorted on root path. + SimplePackageConfig._(this.version, Iterable originalPackages, + List packages, this.extraData) + : _packageTree = _validatePackages(originalPackages, packages), + _packages = {for (var p in packages) p.name: p}; /// Creates empty configuration. /// @@ -27,6 +31,7 @@ class SimplePackageConfig implements PackageConfig { /// found, but code expects a non-null configuration. const SimplePackageConfig.empty() : version = 1, + _packageTree = const EmptyPackageTree(), _packages = const {}, extraData = null; @@ -38,18 +43,28 @@ class SimplePackageConfig implements PackageConfig { return version; } - static Map _validatePackages(Iterable packages) { + static PackageTree _validatePackages( + Iterable originalPackages, List packages) { + // Assumes packages are sorted. Map result = {}; - for (var package in packages) { - if (package is! SimplePackage) { + var tree = MutablePackageTree(); + SimplePackage package; + for (var originalPackage in packages) { + if (originalPackage is! SimplePackage) { // SimplePackage validates these properties. try { - _validatePackageData(package.name, package.root, - package.packageUriRoot, package.languageVersion); + package = SimplePackage( + originalPackage.name, + originalPackage.root, + originalPackage.packageUriRoot, + originalPackage.languageVersion, + originalPackage.extraData); } catch (e) { throw PackageConfigArgumentError( packages, "packages", "Package ${package.name}: ${e.message}"); } + } else { + package = originalPackage; } var name = package.name; if (result.containsKey(name)) { @@ -57,33 +72,31 @@ class SimplePackageConfig implements PackageConfig { name, "packages", "Duplicate package name"); } result[name] = package; - } - - // Check that no root URI is a prefix of another. - if (result.length > 1) { - // Uris cache their toString, so this is not as bad as it looks. - var rootUris = [...result.values] - ..sort((a, b) => a.root.toString().compareTo(b.root.toString())); - var prev = rootUris[0]; - var prevRoot = prev.root.toString(); - for (int i = 1; i < rootUris.length; i++) { - var next = rootUris[i]; - var nextRoot = next.root.toString(); - // If one string is a prefix of another, - // the former sorts just before the latter. - if (nextRoot.startsWith(prevRoot)) { + try { + tree.add(0, package); + } on ConflictException catch (e) { + // There is a conflict with an existing package. + var existingPackage = e.existingPackage; + if (e.isRootConflict) { throw PackageConfigArgumentError( - packages, + originalPackages, "packages", - "Package ${next.name} root overlaps " - "package ${prev.name} root.\n" - "${prev.name} root: $prevRoot\n" - "${next.name} root: $nextRoot\n"); + "Packages ${package.name} and ${existingPackage.name}" + "have the same root directory: ${package.root}.\n"); } - prev = next; + assert(e.isPackageRootConflict); + // Or package is inside the package URI root of the existing package. + throw PackageConfigArgumentError( + originalPackages, + "packages", + "Package ${package.name} is inside the package URI root of " + "package ${existingPackage.name}.\n" + "${existingPackage.name} URI root: " + "${existingPackage.packageUriRoot}\n" + "${package.name} root: ${package.root}\n"); } } - return result; + return tree; } Iterable get packages => _packages.values; @@ -96,14 +109,7 @@ class SimplePackageConfig implements PackageConfig { /// That is, the [Package.rootUri] directory is a parent directory /// of the [file]'s location. /// Returns `null` if the file does not belong to any package. - Package /*?*/ packageOf(Uri file) { - String path = file.toString(); - for (var package in _packages.values) { - var rootPath = package.root.toString(); - if (path.startsWith(rootPath)) return package; - } - return null; - } + Package /*?*/ packageOf(Uri file) => _packageTree.packageOf(file); Uri /*?*/ resolve(Uri packageUri) { String packageName = checkValidPackageUri(packageUri, "packageUri"); @@ -120,12 +126,15 @@ class SimplePackageConfig implements PackageConfig { throw PackageConfigArgumentError(nonPackageUri, "nonPackageUri", "Must not have query or fragment part"); } - for (var package in _packages.values) { - var root = package.packageUriRoot; - if (isUriPrefix(root, nonPackageUri)) { - var rest = nonPackageUri.toString().substring(root.toString().length); - return Uri(scheme: "package", path: "${package.name}/$rest"); - } + // Find package that file belongs to. + var package = _packageTree.packageOf(nonPackageUri); + if (package == null) return null; + // Check if it is inside the package URI root. + var path = nonPackageUri.toString(); + var root = package.packageUriRoot.toString(); + if (_beginsWith(package.root.toString().length, root, path)) { + var rest = path.substring(root.length); + return Uri(scheme: "package", path: "${package.name}/$rest"); } return null; } @@ -142,6 +151,9 @@ class SimplePackage implements Package { SimplePackage._(this.name, this.root, this.packageUriRoot, this.languageVersion, this.extraData); + /// Creates a [SimplePackage] with the provided content. + /// + /// The provided arguments must be valid. factory SimplePackage(String name, Uri root, Uri packageUriRoot, String /*?*/ languageVersion, dynamic extraData) { _validatePackageData(name, root, packageUriRoot, languageVersion); @@ -179,3 +191,144 @@ void _validatePackageData( languageVersion, "languageVersion", "Invalid language version format"); } } + +abstract class PackageTree { + SimplePackage /*?*/ packageOf(Uri file); +} + +/// Packages of a package configuration ordered by root path. +/// +/// A package is said to be inside another package if the root path URI of +/// the latter is a prefix of the root path URI of the former. +/// No two packages of a package may have the same root path, so this +/// path prefix ordering defines a tree-like partial ordering on packages +/// of a configuration. +/// +/// The package tree contains an ordered mapping of unrelated packages +/// (represented by their name) to their immediately nested packages' names. +class MutablePackageTree implements PackageTree { + final List packages = []; + Map /*?*/ _packageChildren; + + /// Tries to (add) `package` to the tree. + /// + /// Throws [ConflictException] if the added package conflicts with an + /// existing package. + /// It conflicts if it has the same root path, or if the new package + /// contains the existing package's package root. + void add(int start, SimplePackage package) { + var path = package.root.toString(); + for (var childPackage in packages) { + var childPath = childPackage.root.toString(); + assert(childPath.length > start); + assert(path.startsWith(childPath.substring(0, start))); + if (_beginsWith(start, childPath, path)) { + var childPathLength = childPath.length; + if (path.length == childPathLength) { + throw ConflictException.root(package, childPackage); + } + var childPackageRoot = childPackage.packageUriRoot.toString(); + if (_beginsWith(childPathLength, childPackageRoot, path)) { + throw ConflictException.packageRoot(package, childPackage); + } + _treeOf(childPackage).add(childPathLength, package); + return; + } + } + packages.add(package); + } + + SimplePackage /*?*/ packageOf(Uri file) { + return findPackageOf(0, file.toString()); + } + + /// Finds package containing [path] in this tree. + /// + /// Returns `null` if no such package is found. + /// + /// Assumes the first [start] characters of path agrees with all + /// the packages at this level of the tree. + SimplePackage /*?*/ findPackageOf(int start, String path) { + for (var childPackage in packages) { + var childPath = childPackage.root.toString(); + if (_beginsWith(start, childPath, path)) { + // The [package] is inside [childPackage]. + var childPathLength = childPath.length; + if (path.length == childPathLength) return childPackage; + var uriRoot = childPackage.packageUriRoot.toString(); + // Is [package] is inside the URI root of [childPackage]. + if (uriRoot.length == childPathLength || + _beginsWith(childPathLength, uriRoot, path)) { + return childPackage; + } + // Otherwise add [package] as child of [childPackage]. + // TODO(lrn): When NNBD comes, convert to: + // return _packageChildren?[childPackage.name] + // ?.packageOf(childPathLength, path) ?? childPackage; + if (_packageChildren == null) return childPackage; + var childTree = _packageChildren[childPackage.name]; + if (childTree == null) return childPackage; + return childTree.findPackageOf(childPathLength, path) ?? childPackage; + } + } + return null; + } + + /// Returns the [PackageTree] of the children of [package]. + /// + /// Ensures that the object is allocated if necessary. + MutablePackageTree _treeOf(SimplePackage package) { + var children = _packageChildren ??= {}; + return children[package.name] ??= MutablePackageTree(); + } +} + +class EmptyPackageTree implements PackageTree { + const EmptyPackageTree(); + + SimplePackage packageOf(Uri file) => null; +} + +/// Checks whether [longerPath] begins with [parentPath]. +/// +/// Skips checking the [start] first characters which are assumed to +/// already have been matched. +bool _beginsWith(int start, String parentPath, String longerPath) { + if (longerPath.length < parentPath.length) return false; + for (int i = start; i < parentPath.length; i++) { + if (longerPath.codeUnitAt(i) != parentPath.codeUnitAt(i)) return false; + } + return true; +} + +/// Conflict between packages added to the same configuration. +/// +/// The [package] conflicts with [existingPackage] if it has +/// the same root path ([isRootConflict]) or the package URI root path +/// of [existingPackage] is inside the root path of [package] +/// ([isPackageRootConflict]). +class ConflictException { + /// The existing package that [package] conflicts with. + final SimplePackage existingPackage; + + /// The package that could not be added without a conflict. + final SimplePackage package; + + /// Whether the conflict is with the package URI root of [existingPackage]. + final bool isPackageRootConflict; + + /// Creates a root conflict between [package] and [existingPackage]. + ConflictException.root(this.package, this.existingPackage) + : isPackageRootConflict = false; + + /// Creates a package root conflict between [package] and [existingPackage]. + ConflictException.packageRoot(this.package, this.existingPackage) + : isPackageRootConflict = true; + + /// WHether the conflict is with the root URI of [existingPackage]. + bool get isRootConflict => !isPackageRootConflict; +} + +/// Used for sorting packages by root path. +int _compareRoot(Package p1, Package p2) => + p1.root.toString().compareTo(p2.root.toString()); diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 8a6014cad..8108102bd 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -7,7 +7,7 @@ import "dart:io"; import "dart:typed_data"; import 'package:charcode/ascii.dart'; -import "package:path/path.dart" as path; +import "package:path/path.dart" as p; import "discovery.dart" show packageConfigJsonPath; import "errors.dart"; @@ -38,36 +38,42 @@ const String _generatorVersionKey = "generatorVersion"; /// Detects whether the [file] is a version one `.packages` file or /// a version two `package_config.json` file. /// -/// If the [file] is a `.packages` file, first checks whether there is an -/// adjacent `.dart_tool/package_config.json` file, and if so, -/// reads that instead. +/// If the [file] is a `.packages` file and [preferNewest] is true, +/// first checks whether there is an adjacent `.dart_tool/package_config.json` +/// file, and if so, reads that instead. +/// If [preferNewset] is false, the specified file is loaded even if it is +/// a `.packages` file and there is an available `package_config.json` file. /// /// The file must exist and be a normal file. -Future readAnyConfigFile(File file) async { +Future readAnyConfigFile(File file, bool preferNewest) async { var bytes = await file.readAsBytes(); int firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { // Definitely not a JSON object, probably a .packages. - var alternateFile = File(path.join( - path.dirname(file.path), ".dart_tool", "package_config.json")); - if (!alternateFile.existsSync()) { - return packages_file.parse(bytes, file.uri); + if (preferNewest) { + var alternateFile = File( + p.join(p.dirname(file.path), ".dart_tool", "package_config.json")); + if (alternateFile.existsSync()) { + return parsePackageConfigBytes( + await alternateFile.readAsBytes(), alternateFile.uri); + } } - file = alternateFile; - bytes = await alternateFile.readAsBytes(); + return packages_file.parse(bytes, file.uri); } return parsePackageConfigBytes(bytes, file.uri); } /// Like [readAnyConfigFile] but uses a URI and an optional loader. -Future readAnyConfigFileUri( - Uri file, Future loader(Uri uri) /*?*/) async { +Future readAnyConfigFileUri(Uri file, + Future loader(Uri uri) /*?*/, bool preferNewest) async { if (file.isScheme("package")) { throw PackageConfigArgumentError( file, "file", "Must not be a package: URI"); } if (loader == null) { - if (file.isScheme("file")) return readAnyConfigFile(File.fromUri(file)); + if (file.isScheme("file")) { + return readAnyConfigFile(File.fromUri(file), preferNewest); + } loader = defaultLoader; } var bytes = await loader(file); @@ -78,13 +84,15 @@ Future readAnyConfigFileUri( int firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { // Definitely not a JSON object, probably a .packages. - var alternateFile = file.resolveUri(packageConfigJsonPath); - var alternateBytes = await loader(alternateFile); - if (alternateBytes == null) { - return packages_file.parse(bytes, file); + if (preferNewest) { + // Check if there is a package_config.json file. + var alternateFile = file.resolveUri(packageConfigJsonPath); + var alternateBytes = await loader(alternateFile); + if (alternateBytes != null) { + return parsePackageConfigBytes(alternateBytes, alternateFile); + } } - bytes = alternateBytes; - file = alternateFile; + return packages_file.parse(bytes, file); } return parsePackageConfigBytes(bytes, file); } @@ -242,8 +250,8 @@ PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { Future writePackageConfigJson( PackageConfig config, Directory targetDirectory) async { // Write .dart_tool/package_config.json first. - var file = File( - path.join(targetDirectory.path, ".dart_tool", "package_config.json")); + var file = + File(p.join(targetDirectory.path, ".dart_tool", "package_config.json")); var baseUri = file.uri; var extraData = config.extraData; var data = { @@ -275,7 +283,7 @@ Future writePackageConfigJson( "${generated != null ? " on $generated" : ""}."; } } - file = File(path.join(targetDirectory.path, ".packages")); + file = File(p.join(targetDirectory.path, ".packages")); baseUri = file.uri; var buffer = StringBuffer(); packages_file.write(buffer, config, baseUri: baseUri, comment: comment); @@ -313,7 +321,7 @@ Map /*?*/ _extractExtraData( /// Checks that the object is a valid JSON-like data structure. bool _validateJson(dynamic object) { - if (object == null || object == true || object == false) return true; + if (object == null || true == object || false == object) return true; if (object is num || object is String) return true; if (object is List) { for (var element in object) if (!_validateJson(element)) return false; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 0cd7ddc52..781dc32a8 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=2.5.0-dev <3.0.0' + sdk: '>=2.7.0 <3.0.0' dependencies: charcode: ^1.1.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 5db24a100..4dd1504e1 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -170,6 +170,13 @@ main() { expect(config.version, 2); validatePackagesFile(config, directory); }); + fileTest("prefer .packages", files, (Directory directory) async { + File file = dirFile(directory, ".packages"); + PackageConfig config = + await loadPackageConfig(file, preferNewest: false); + expect(config.version, 1); + validatePackagesFile(config, directory); + }); }); fileTest("package_config.json non-default name", { diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 414a43add..9558f585e 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -4,7 +4,6 @@ library package_config.discovery_test; -import "dart:io"; import "package:test/test.dart"; import "package:package_config_2/package_config.dart"; diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 235f49381..a07ef1d61 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -2,7 +2,6 @@ // 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. -import "dart:io"; import "dart:convert"; import "package:test/test.dart"; @@ -199,9 +198,43 @@ void main() { expect(config.packages.first.name, "foo"); }); + test("nested packages", () { + var configBytes = utf8.encode(json.encode({ + "configVersion": 2, + "packages": [ + {"name": "foo", "rootUri": "/foo/", "packageUri": "lib/"}, + {"name": "bar", "rootUri": "/foo/bar/", "packageUri": "lib/"}, + {"name": "baz", "rootUri": "/foo/bar/baz/", "packageUri": "lib/"}, + {"name": "qux", "rootUri": "/foo/qux/", "packageUri": "lib/"}, + ] + })); + var config = parsePackageConfigBytes( + configBytes, Uri.parse("file:///tmp/.dart_tool/file.dart")); + expect(config.version, 2); + expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart")).name, + "foo"); + expect( + config.packageOf(Uri.parse("file:///foo/bar/lala.dart")).name, "bar"); + expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart")).name, + "baz"); + expect( + config.packageOf(Uri.parse("file:///foo/qux/lala.dart")).name, "qux"); + expect(config.toPackageUri(Uri.parse("file:///foo/lib/diz")), + Uri.parse("package:foo/diz")); + expect(config.toPackageUri(Uri.parse("file:///foo/bar/lib/diz")), + Uri.parse("package:bar/diz")); + expect(config.toPackageUri(Uri.parse("file:///foo/bar/baz/lib/diz")), + Uri.parse("package:baz/diz")); + expect(config.toPackageUri(Uri.parse("file:///foo/qux/lib/diz")), + Uri.parse("package:qux/diz")); + }); + group("invalid", () { testThrows(String name, String source) { test(name, () { + if (name == "inside lib") { + print(name); + } expect( () => parsePackageConfigBytes(utf8.encode(source), Uri.parse("file:///tmp/.dart_tool/file.dart")), @@ -304,9 +337,15 @@ void main() { testThrows("same roots", '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); testThrows( - "overlapping roots", - '{$cfg,"packages":[{$name,$root},' - '{"name":"bar","rootUri":"/foo/sub/"}]}'); + // The roots of foo and bar are the same. + "same roots", + '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); + testThrows( + // The root of bar is inside the package root of foo. + "inside lib", + '{$cfg,"packages":[' + '{"name":"foo","rootUri":"/foo/","packageUri":"lib/"},' + '{"name":"bar","rootUri":"/foo/lib/qux/"}]}'); }); }); } From db13ed8bf9e2ad1700ef155249d5e8bac2c8b453 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 27 Jan 2020 13:07:43 +0100 Subject: [PATCH 129/281] Prepare release of package_config 2.0.0. --- pkgs/package_config/README.md | 8 +++++--- pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 942822002..9ab7f38a3 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,8 +1,10 @@ # package_config -Support for working with **Package Resolution Configuration** files as described -in this [DEP](https://github.com/lrhn/dep-pkgspec/blob/master/DEP-pkgspec.md), -under review [here](https://github.com/dart-lang/dart_enhancement_proposals/issues/5). +Support for working with **Package Configuration** files as described +in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). + +This package is also available as `package_config_2`, which can be used by packages +which transitively depend on a version of package_config with a version <2.0.0. [![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 781dc32a8..66aeb7858 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,4 +1,4 @@ -name: package_config_2 +name: package_config version: 2.0.0 description: Support for working with Package Configuration files. author: Dart Team From 9bb0203bb07039889f2df85f045382692d7ffe88 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 27 Jan 2020 13:07:43 +0100 Subject: [PATCH 130/281] Prepare release of package_config 2.0.0. --- pkgs/package_config/README.md | 5 +++-- pkgs/package_config/test/discovery_test.dart | 2 +- pkgs/package_config/test/discovery_uri_test.dart | 2 +- pkgs/package_config/test/parse_test.dart | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 9ab7f38a3..073a1c7e0 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -3,8 +3,9 @@ Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). -This package is also available as `package_config_2`, which can be used by packages -which transitively depend on a version of package_config with a version <2.0.0. +This version of the `package_config` package is also available as `package_config_2`, +which can be used by packages which transitively depend on a version of `package_config` +with a version <2.0.0. [![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 4dd1504e1..3256187d2 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -6,7 +6,7 @@ library package_config.discovery_test; import "dart:io"; import "package:test/test.dart"; -import "package:package_config_2/package_config.dart"; +import "package:package_config/package_config.dart"; import "src/util.dart"; diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 9558f585e..8ad428ac0 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -5,7 +5,7 @@ library package_config.discovery_test; import "package:test/test.dart"; -import "package:package_config_2/package_config.dart"; +import "package:package_config/package_config.dart"; import "src/util.dart"; diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index a07ef1d61..3d1a20e4a 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -6,8 +6,8 @@ import "dart:convert"; import "package:test/test.dart"; -import "package:package_config_2/src/packages_file.dart" as packages; -import "package:package_config_2/src/package_config_json.dart"; +import "package:package_config/src/packages_file.dart" as packages; +import "package:package_config/src/package_config_json.dart"; import "src/util.dart"; void main() { From 86f3c5245a3aac86783819a35153b20c80fe0557 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 11 Feb 2020 09:34:11 +0100 Subject: [PATCH 131/281] Make error handling optionally more permissive. (dart-lang/package_config#58) * Make error handling optionally more permissive. * Make the LanguageVersion be an object, not a string. * Make it version 3.0.0-dev --- pkgs/package_config/CHANGELOG.md | 19 +- pkgs/package_config/README.md | 6 +- pkgs/package_config/lib/package_config.dart | 49 ++- pkgs/package_config/lib/src/discovery.dart | 48 +-- pkgs/package_config/lib/src/errors.dart | 57 +-- .../lib/src/package_config.dart | 122 ++++++- .../lib/src/package_config_impl.dart | 331 +++++++++++++----- .../lib/src/package_config_json.dart | 194 +++++++--- .../package_config/lib/src/packages_file.dart | 91 +++-- pkgs/package_config/lib/src/util.dart | 118 ++++--- pkgs/package_config/pubspec.yaml | 6 +- pkgs/package_config/test/discovery_test.dart | 119 +++++-- .../test/discovery_uri_test.dart | 43 ++- pkgs/package_config/test/parse_test.dart | 63 ++-- pkgs/package_config/test/src/util.dart | 8 +- 15 files changed, 917 insertions(+), 357 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 84384fc21..317184075 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,9 +1,22 @@ +## 3.0.0 + +- Make the language version be represented as a `LanguageVersion` class + instead of a string. +- Made error handling interceptable. Passing an `onError` handler + makes the parsers attempt to do a best-effort error correction after + detecting an error. +- Do not require root URIs to have paths starting with `/`. That + only makes sense for `file` or `http`, and they enforce it anyway. +- Fixed bug in language version validation not accepting the digit `9`. + ## 2.0.0 - - Based on new JSON file format with more content. + +- Based on new JSON file format with more content. ## 1.2.0 - - Added support for writing default-package entries. - - Fixed bug when writing `Uri`s containing a fragment. + +- Added support for writing default-package entries. +- Fixed bug when writing `Uri`s containing a fragment. ## 1.1.0 diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 073a1c7e0..45791aaf3 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -3,11 +3,7 @@ Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). -This version of the `package_config` package is also available as `package_config_2`, -which can be used by packages which transitively depend on a version of `package_config` -with a version <2.0.0. - -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) ## Features and bugs diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 77e8d61bf..98b31f1f9 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -8,11 +8,14 @@ library package_config.package_config; import "dart:io" show File, Directory; import "dart:typed_data" show Uint8List; + import "src/discovery.dart" as discover; +import "src/errors.dart" show throwError; import "src/package_config.dart"; import "src/package_config_json.dart"; -export "src/package_config.dart" show PackageConfig, Package; +export "src/package_config.dart" + show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; export "src/errors.dart" show PackageConfigError; /// Reads a specific package configuration file. @@ -30,9 +33,15 @@ export "src/errors.dart" show PackageConfigError; /// is loaded even if there is an available `package_config.json` file. /// The caller can determine this from the [PackageConfig.version] /// being 1 and look for a `package_config.json` file themselves. +/// +/// If [onError] is provided, the configuration file parsing will report errors +/// by calling that function, and then try to recover. +/// The returned package configuration is a *best effort* attempt to create +/// a valid configuration from the invalid configuration file. +/// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfig(File file, - {bool preferNewest = true}) => - readAnyConfigFile(file, preferNewest); + {bool preferNewest = true, void onError(Object error)}) => + readAnyConfigFile(file, preferNewest, onError ?? throwError); /// Reads a specific package configuration URI. /// @@ -68,10 +77,17 @@ Future loadPackageConfig(File file, /// of an I/O issue, as long as the location URIs are valid. /// As such, it does not distinguish between a file not existing, /// and it being temporarily locked or unreachable. +/// +/// If [onError] is provided, the configuration file parsing will report errors +/// by calling that function, and then try to recover. +/// The returned package configuration is a *best effort* attempt to create +/// a valid configuration from the invalid configuration file. +/// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfigUri(Uri file, {Future loader(Uri uri) /*?*/, - bool preferNewest = true}) => - readAnyConfigFileUri(file, loader, preferNewest); + bool preferNewest = true, + void onError(Object error)}) => + readAnyConfigFileUri(file, loader, onError ?? throwError, preferNewest); /// Finds a package configuration relative to [directory]. /// @@ -86,10 +102,16 @@ Future loadPackageConfigUri(Uri file, /// If [recurse] is set to [false], this parent directory check is not /// performed. /// +/// If [onError] is provided, the configuration file parsing will report errors +/// by calling that function, and then try to recover. +/// The returned package configuration is a *best effort* attempt to create +/// a valid configuration from the invalid configuration file. +/// If no [onError] is provided, errors are thrown immediately. +/// /// Returns `null` if no configuration file is found. Future findPackageConfig(Directory directory, - {bool recurse = true}) => - discover.findPackageConfig(directory, recurse); + {bool recurse = true, void onError(Object error)}) => + discover.findPackageConfig(directory, recurse, onError ?? throwError); /// Finds a package configuration relative to [location]. /// @@ -124,10 +146,19 @@ Future findPackageConfig(Directory directory, /// As such, it does not distinguish between a file not existing, /// and it being temporarily locked or unreachable. /// +/// If [onError] is provided, the configuration file parsing will report errors +/// by calling that function, and then try to recover. +/// The returned package configuration is a *best effort* attempt to create +/// a valid configuration from the invalid configuration file. +/// If no [onError] is provided, errors are thrown immediately. +/// /// Returns `null` if no configuration file is found. Future findPackageConfigUri(Uri location, - {bool recurse = true, Future loader(Uri uri)}) => - discover.findPackageConfigUri(location, loader, recurse); + {bool recurse = true, + Future loader(Uri uri), + void onError(Object error)}) => + discover.findPackageConfigUri( + location, loader, onError ?? throwError, recurse); /// Writes a package configuration to the provided directory. /// diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 5ad6ac54e..14033ed35 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -5,13 +5,11 @@ import "dart:io"; import 'dart:typed_data'; -import "package:path/path.dart" as p; - import "errors.dart"; import "package_config_impl.dart"; import "package_config_json.dart"; import "packages_file.dart" as packages_file; -import "util.dart" show defaultLoader; +import "util.dart" show defaultLoader, pathJoin; final Uri packageConfigJsonPath = Uri(path: ".dart_tool/package_config.json"); final Uri dotPackagesPath = Uri(path: ".packages"); @@ -33,7 +31,7 @@ final Uri parentPath = Uri(path: ".."); /// Returns `null` if no configuration was found. If a configuration /// is needed, then the caller can supply [PackageConfig.empty]. Future findPackageConfig( - Directory baseDirectory, bool recursive) async { + Directory baseDirectory, bool recursive, void onError(Object error)) async { var directory = baseDirectory; if (!directory.isAbsolute) directory = directory.absolute; if (!await directory.exists()) { @@ -41,7 +39,7 @@ Future findPackageConfig( } do { // Check for $cwd/.packages - var packageConfig = await findPackagConfigInDirectory(directory); + var packageConfig = await findPackagConfigInDirectory(directory, onError); if (packageConfig != null) return packageConfig; if (!recursive) break; // Check in parent directories. @@ -53,16 +51,22 @@ Future findPackageConfig( } /// Similar to [findPackageConfig] but based on a URI. -Future findPackageConfigUri(Uri location, - Future loader(Uri uri) /*?*/, bool recursive) async { +Future findPackageConfigUri( + Uri location, + Future loader(Uri uri) /*?*/, + void onError(Object error) /*?*/, + bool recursive) async { if (location.isScheme("package")) { - throw PackageConfigArgumentError( - location, "location", "Must not be a package: URI"); + onError(PackageConfigArgumentError( + location, "location", "Must not be a package: URI")); + return null; } if (loader == null) { if (location.isScheme("file")) { return findPackageConfig( - Directory.fromUri(location.resolveUri(currentPath)), recursive); + Directory.fromUri(location.resolveUri(currentPath)), + recursive, + onError); } loader = defaultLoader; } @@ -71,12 +75,12 @@ Future findPackageConfigUri(Uri location, var file = location.resolveUri(packageConfigJsonPath); var bytes = await loader(file); if (bytes != null) { - return parsePackageConfigBytes(bytes, file); + return parsePackageConfigBytes(bytes, file, onError); } file = location.resolveUri(dotPackagesPath); bytes = await loader(file); if (bytes != null) { - return packages_file.parse(bytes, file); + return packages_file.parse(bytes, file, onError); } if (!recursive) break; var parent = location.resolveUri(parentPath); @@ -90,33 +94,35 @@ Future findPackageConfigUri(Uri location, /// /// Loads the file, if it is there, and returns the resulting [PackageConfig]. /// Returns `null` if the file isn't there. -/// Throws [FormatException] if a file is there but is not valid. +/// Reports a [FormatException] if a file is there but the content is not valid. +/// If the file exists, but fails to be read, the file system error is reported. /// -/// If [extraData] is supplied and the `package_config.json` contains extra -/// entries in the top JSON object, those extra entries are stored into -/// [extraData]. +/// If [onError] is supplied, parsing errors are reported using that, and +/// a best-effort attempt is made to return a package configuration. +/// This may be the empty package configuration. Future findPackagConfigInDirectory( - Directory directory) async { + Directory directory, void onError(Object error)) async { var packageConfigFile = await checkForPackageConfigJsonFile(directory); if (packageConfigFile != null) { - return await readPackageConfigJsonFile(packageConfigFile); + return await readPackageConfigJsonFile(packageConfigFile, onError); } packageConfigFile = await checkForDotPackagesFile(directory); if (packageConfigFile != null) { - return await readDotPackagesFile(packageConfigFile); + return await readDotPackagesFile(packageConfigFile, onError); } return null; } Future /*?*/ checkForPackageConfigJsonFile(Directory directory) async { assert(directory.isAbsolute); - var file = File(p.join(directory.path, ".dart_tool", "package_config.json")); + var file = + File(pathJoin(directory.path, ".dart_tool", "package_config.json")); if (await file.exists()) return file; return null; } Future checkForDotPackagesFile(Directory directory) async { - var file = File(p.join(directory.path, ".packages")); + var file = File(pathJoin(directory.path, ".packages")); if (await file.exists()) return file; return null; } diff --git a/pkgs/package_config/lib/src/errors.dart b/pkgs/package_config/lib/src/errors.dart index 6c31ccea1..c9736177c 100644 --- a/pkgs/package_config/lib/src/errors.dart +++ b/pkgs/package_config/lib/src/errors.dart @@ -1,24 +1,33 @@ -// Copyright (c) 2019, 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. - -/// General superclass of most errors and exceptions thrown by this package. -/// -/// Only covers errors thrown while parsing package configuration files. -/// Programming errors and I/O exceptions are not covered. -abstract class PackageConfigError { - PackageConfigError._(); -} - -class PackageConfigArgumentError extends ArgumentError - implements PackageConfigError { - PackageConfigArgumentError(Object /*?*/ value, String name, String message) - : super.value(value, name, message); -} - -class PackageConfigFormatException extends FormatException - implements PackageConfigError { - PackageConfigFormatException(String message, Object /*?*/ value, - [int /*?*/ index]) - : super(message, value, index); -} +// Copyright (c) 2019, 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. + +/// General superclass of most errors and exceptions thrown by this package. +/// +/// Only covers errors thrown while parsing package configuration files. +/// Programming errors and I/O exceptions are not covered. +abstract class PackageConfigError { + PackageConfigError._(); +} + +class PackageConfigArgumentError extends ArgumentError + implements PackageConfigError { + PackageConfigArgumentError(Object /*?*/ value, String name, String message) + : super.value(value, name, message); + + PackageConfigArgumentError.from(ArgumentError error) + : super.value(error.invalidValue, error.name, error.message); +} + +class PackageConfigFormatException extends FormatException + implements PackageConfigError { + PackageConfigFormatException(String message, Object /*?*/ source, + [int /*?*/ offset]) + : super(message, source, offset); + + PackageConfigFormatException.from(FormatException exception) + : super(exception.message, exception.source, exception.offset); +} + +/// The default `onError` handler. +void /*Never*/ throwError(Object error) => throw error; diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index f7b96b8a5..08c4a9691 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -2,6 +2,7 @@ // 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. +import 'errors.dart'; import "package_config_impl.dart"; /// A package configuration. @@ -34,7 +35,7 @@ abstract class PackageConfig { /// /// The version of the resulting configuration is always [maxVersion]. factory PackageConfig(Iterable packages, {dynamic extraData}) => - SimplePackageConfig(maxVersion, packages); + SimplePackageConfig(maxVersion, packages, extraData); /// The configuration version number. /// @@ -124,9 +125,10 @@ abstract class Package { /// [Package.extraData] of the created package. factory Package(String name, Uri root, {Uri /*?*/ packageUriRoot, - String /*?*/ languageVersion, + LanguageVersion /*?*/ languageVersion, dynamic extraData}) => - SimplePackage(name, root, packageUriRoot, languageVersion, extraData); + SimplePackage.validate( + name, root, packageUriRoot, languageVersion, extraData, throwError); /// The package-name of the package. String get name; @@ -156,16 +158,9 @@ abstract class Package { /// Each package may have a default language version associated, /// which is the language version used to parse and compile /// Dart files in the package. - /// A package version is always of the form: - /// - /// * A numeral consisting of one or more decimal digits, - /// with no leading zero unless the entire numeral is a single zero digit. - /// * Followed by a `.` character. - /// * Followed by another numeral of the same form. - /// - /// There is no whitespace allowed around the numerals. - /// Valid version numbers include `2.5`, `3.0`, and `1234.5678`. - String /*?*/ get languageVersion; + /// A package version is defined by two non-negative numbers, + /// the *major* and *minor* version numbers. + LanguageVersion /*?*/ get languageVersion; /// Extra data associated with the specific package. /// @@ -174,3 +169,104 @@ abstract class Package { /// JSON-like list/map data structures. dynamic get extraData; } + +/// A language version. +/// +/// A language version is represented by two non-negative integers, +/// the [major] and [minor] version numbers. +/// +/// If errors during parsing are handled using an `onError` handler, +/// then an *invalid* language version may be represented by an +/// [InvalidLanguageVersion] object. +abstract class LanguageVersion implements Comparable { + /// The maximal value allowed by [major] and [minor] values; + static const int maxValue = 0x7FFFFFFF; + factory LanguageVersion(int major, int minor) { + RangeError.checkValueInInterval(major, 0, maxValue, "major"); + RangeError.checkValueInInterval(minor, 0, maxValue, "major"); + return SimpleLanguageVersion(major, minor, null); + } + + /// Parses a language version string. + /// + /// A valid language version string has the form + /// + /// > *decimalNumber* `.` *decimalNumber* + /// + /// where a *decimalNumber* is a non-empty sequence of decimal digits + /// with no unnecessary leading zeros (the decimal number only starts + /// with a zero digit if that digit is the entire number). + /// No spaces are allowed in the string. + /// + /// If the [source] is valid then it is parsed into a valid + /// [LanguageVersion] object. + /// If not, then the [onError] is called with a [FormatException]. + /// If [onError] is not supplied, it defaults to throwing the exception. + /// If the call does not throw, then an [InvalidLanguageVersion] is returned + /// containing the original [source]. + static LanguageVersion parse(String source, {void onError(Object error)}) => + parseLanguageVersion(source, onError ?? throwError); + + /// The major language version. + /// + /// A non-negative integer less than 231. + /// + /// The value is negative for objects representing *invalid* language + /// versions ([InvalidLanguageVersion]). + int get major; + + /// The minor language version. + /// + /// A non-negative integer less than 231. + /// + /// The value is negative for objects representing *invalid* language + /// versions ([InvalidLanguageVersion]). + int get minor; + + /// Compares language versions. + /// + /// Two language versions are considered equal if they have the + /// same major and minor version numbers. + /// + /// A language version is greater then another if the former's major version + /// is greater than the latter's major version, or if they have + /// the same major version and the former's minor version is greater than + /// the latter's. + int compareTo(LanguageVersion other); + + /// Valid language versions with the same [major] and [minor] values are + /// equal. + /// + /// Invalid language versions ([InvalidLanguageVersion]) are not equal to + /// any other object. + bool operator ==(Object other); + + int get hashCode; + + /// A string representation of the language version. + /// + /// A valid language version is represented as + /// `"${version.major}.${version.minor}"`. + String toString(); +} + +/// An *invalid* language version. +/// +/// Stored in a [Package] when the orginal language version string +/// was invalid and a `onError` handler was passed to the parser +/// which did not throw on an error. +abstract class InvalidLanguageVersion implements LanguageVersion { + /// The value -1 for an invalid language version. + int get major; + + /// The value -1 for an invalid language version. + int get minor; + + /// An invalid language version is only equal to itself. + bool operator ==(Object other); + + int get hashCode; + + /// The original invalid version string. + String toString(); +} diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 62579610c..39633fe4b 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -14,16 +14,18 @@ class SimplePackageConfig implements PackageConfig { final PackageTree _packageTree; final dynamic extraData; - SimplePackageConfig(int version, Iterable packages, - [dynamic extraData]) - : this._(_validateVersion(version), packages, - [...packages]..sort(_compareRoot), extraData); + factory SimplePackageConfig(int version, Iterable packages, + [dynamic extraData, void onError(Object error)]) { + onError ??= throwError; + var validVersion = _validateVersion(version, onError); + var sortedPackages = [...packages]..sort(_compareRoot); + var packageTree = _validatePackages(packages, sortedPackages, onError); + return SimplePackageConfig._(validVersion, packageTree, + {for (var p in packageTree.allPackages) p.name: p}, extraData); + } - /// Expects a list of [packages] sorted on root path. - SimplePackageConfig._(this.version, Iterable originalPackages, - List packages, this.extraData) - : _packageTree = _validatePackages(originalPackages, packages), - _packages = {for (var p in packages) p.name: p}; + SimplePackageConfig._( + this.version, this._packageTree, this._packages, this.extraData); /// Creates empty configuration. /// @@ -35,66 +37,78 @@ class SimplePackageConfig implements PackageConfig { _packages = const {}, extraData = null; - static int _validateVersion(int version) { + static int _validateVersion(int version, void onError(Object error)) { if (version < 0 || version > PackageConfig.maxVersion) { - throw PackageConfigArgumentError(version, "version", - "Must be in the range 1 to ${PackageConfig.maxVersion}"); + onError(PackageConfigArgumentError(version, "version", + "Must be in the range 1 to ${PackageConfig.maxVersion}")); + return 2; // The minimal version supporting a SimplePackageConfig. } return version; } - static PackageTree _validatePackages( - Iterable originalPackages, List packages) { - // Assumes packages are sorted. - Map result = {}; + static PackageTree _validatePackages(Iterable originalPackages, + List packages, void onError(Object error)) { + var packageNames = {}; var tree = MutablePackageTree(); - SimplePackage package; for (var originalPackage in packages) { + if (originalPackage == null) { + onError(ArgumentError.notNull("element of packages")); + continue; + } + SimplePackage package; if (originalPackage is! SimplePackage) { // SimplePackage validates these properties. - try { - package = SimplePackage( - originalPackage.name, - originalPackage.root, - originalPackage.packageUriRoot, - originalPackage.languageVersion, - originalPackage.extraData); - } catch (e) { - throw PackageConfigArgumentError( - packages, "packages", "Package ${package.name}: ${e.message}"); - } + package = SimplePackage.validate( + originalPackage.name, + originalPackage.root, + originalPackage.packageUriRoot, + originalPackage.languageVersion, + originalPackage.extraData, (error) { + if (error is PackageConfigArgumentError) { + onError(PackageConfigArgumentError(packages, "packages", + "Package ${package.name}: ${error.message}")); + } else { + onError(error); + } + }); + if (package == null) continue; } else { package = originalPackage; } var name = package.name; - if (result.containsKey(name)) { - throw PackageConfigArgumentError( - name, "packages", "Duplicate package name"); + if (packageNames.contains(name)) { + onError(PackageConfigArgumentError( + name, "packages", "Duplicate package name")); + continue; } - result[name] = package; - try { - tree.add(0, package); - } on ConflictException catch (e) { - // There is a conflict with an existing package. - var existingPackage = e.existingPackage; - if (e.isRootConflict) { - throw PackageConfigArgumentError( - originalPackages, - "packages", - "Packages ${package.name} and ${existingPackage.name}" - "have the same root directory: ${package.root}.\n"); + packageNames.add(name); + tree.add(0, package, (error) { + if (error is ConflictException) { + // There is a conflict with an existing package. + var existingPackage = error.existingPackage; + if (error.isRootConflict) { + onError(PackageConfigArgumentError( + originalPackages, + "packages", + "Packages ${package.name} and ${existingPackage.name}" + "have the same root directory: ${package.root}.\n")); + } else { + assert(error.isPackageRootConflict); + // Package is inside the package URI root of the existing package. + onError(PackageConfigArgumentError( + originalPackages, + "packages", + "Package ${package.name} is inside the package URI root of " + "package ${existingPackage.name}.\n" + "${existingPackage.name} URI root: " + "${existingPackage.packageUriRoot}\n" + "${package.name} root: ${package.root}\n")); + } + } else { + // Any other error. + onError(error); } - assert(e.isPackageRootConflict); - // Or package is inside the package URI root of the existing package. - throw PackageConfigArgumentError( - originalPackages, - "packages", - "Package ${package.name} is inside the package URI root of " - "package ${existingPackage.name}.\n" - "${existingPackage.name} URI root: " - "${existingPackage.packageUriRoot}\n" - "${package.name} root: ${package.root}\n"); - } + }); } return tree; } @@ -145,7 +159,7 @@ class SimplePackage implements Package { final String name; final Uri root; final Uri packageUriRoot; - final String /*?*/ languageVersion; + final LanguageVersion /*?*/ languageVersion; final dynamic extraData; SimplePackage._(this.name, this.root, this.packageUriRoot, @@ -154,45 +168,175 @@ class SimplePackage implements Package { /// Creates a [SimplePackage] with the provided content. /// /// The provided arguments must be valid. - factory SimplePackage(String name, Uri root, Uri packageUriRoot, - String /*?*/ languageVersion, dynamic extraData) { - _validatePackageData(name, root, packageUriRoot, languageVersion); + /// + /// If the arguments are invalid then the error is reported by + /// calling [onError], then the erroneous entry is ignored. + /// + /// If [onError] is provided, the user is expected to be able to handle + /// errors themselves. An invalid [languageVersion] string + /// will be replaced with the string `"invalid"`. This allows + /// users to detect the difference between an absent version and + /// an invalid one. + /// + /// Returns `null` if the input is invalid and an approximately valid package + /// cannot be salvaged from the input. + static SimplePackage /*?*/ validate( + String name, + Uri root, + Uri packageUriRoot, + LanguageVersion /*?*/ languageVersion, + dynamic extraData, + void onError(Object error)) { + bool fatalError = false; + var invalidIndex = checkPackageName(name); + if (invalidIndex >= 0) { + onError(PackageConfigFormatException( + "Not a valid package name", name, invalidIndex)); + fatalError = true; + } + if (root.isScheme("package")) { + onError(PackageConfigArgumentError( + "$root", "root", "Must not be a package URI")); + fatalError = true; + } else if (!isAbsoluteDirectoryUri(root)) { + onError(PackageConfigArgumentError( + "$root", + "root", + "In package $name: Not an absolute URI with no query or fragment " + "with a path ending in /")); + // Try to recover. If the URI has a scheme, + // then ensure that the path ends with `/`. + if (!root.hasScheme) { + fatalError = true; + } else if (!root.path.endsWith("/")) { + root = root.replace(path: root.path + "/"); + } + } + if (!fatalError) { + if (!isAbsoluteDirectoryUri(packageUriRoot)) { + onError(PackageConfigArgumentError( + packageUriRoot, + "packageUriRoot", + "In package $name: Not an absolute URI with no query or fragment " + "with a path ending in /")); + packageUriRoot = root; + } else if (!isUriPrefix(root, packageUriRoot)) { + onError(PackageConfigArgumentError(packageUriRoot, "packageUriRoot", + "The package URI root is not below the package root")); + packageUriRoot = root; + } + } + if (fatalError) return null; return SimplePackage._( name, root, packageUriRoot, languageVersion, extraData); } } -void _validatePackageData( - String name, Uri root, Uri packageUriRoot, String /*?*/ languageVersion) { - if (!isValidPackageName(name)) { - throw PackageConfigArgumentError(name, "name", "Not a valid package name"); +/// Checks whether [version] is a valid Dart language version string. +/// +/// The format is (as RegExp) `^(0|[1-9]\d+)\.(0|[1-9]\d+)$`. +/// +/// Reports a format exception on [onError] if not, or if the numbers +/// are too large (at most 32-bit signed integers). +LanguageVersion parseLanguageVersion( + String source, void onError(Object error)) { + var index = 0; + // Reads a positive decimal numeral. Returns the value of the numeral, + // or a negative number in case of an error. + // Starts at [index] and increments the index to the position after + // the numeral. + // It is an error if the numeral value is greater than 0x7FFFFFFFF. + // It is a recoverable error if the numeral starts with leading zeros. + int readNumeral() { + const maxValue = 0x7FFFFFFF; + if (index == source.length) { + onError(PackageConfigFormatException("Missing number", source, index)); + return -1; + } + var start = index; + + var char = source.codeUnitAt(index); + var digit = char ^ 0x30; + if (digit > 9) { + onError(PackageConfigFormatException("Missing number", source, index)); + return -1; + } + var firstDigit = digit; + var value = 0; + do { + value = value * 10 + digit; + if (value > maxValue) { + onError( + PackageConfigFormatException("Number too large", source, start)); + return -1; + } + index++; + if (index == source.length) break; + char = source.codeUnitAt(index); + digit = char ^ 0x30; + } while (digit <= 9); + if (firstDigit == 0 && index > start + 1) { + onError(PackageConfigFormatException( + "Leading zero not allowed", source, start)); + } + return value; + } + + var major = readNumeral(); + if (major < 0) { + return SimpleInvalidLanguageVersion(source); } - if (!isAbsoluteDirectoryUri(root)) { - throw PackageConfigArgumentError( - "$root", - "root", - "Not an absolute URI with no query or fragment " - "with a path ending in /"); + if (index == source.length || source.codeUnitAt(index) != $dot) { + onError(PackageConfigFormatException("Missing '.'", source, index)); + return SimpleInvalidLanguageVersion(source); } - if (!isAbsoluteDirectoryUri(packageUriRoot)) { - throw PackageConfigArgumentError( - packageUriRoot, - "packageUriRoot", - "Not an absolute URI with no query or fragment " - "with a path ending in /"); + index++; + var minor = readNumeral(); + if (minor < 0) { + return SimpleInvalidLanguageVersion(source); } - if (!isUriPrefix(root, packageUriRoot)) { - throw PackageConfigArgumentError(packageUriRoot, "packageUriRoot", - "The package URI root is not below the package root"); + if (index != source.length) { + onError(PackageConfigFormatException( + "Unexpected trailing character", source, index)); + return SimpleInvalidLanguageVersion(source); } - if (languageVersion != null && - checkValidVersionNumber(languageVersion) >= 0) { - throw PackageConfigArgumentError( - languageVersion, "languageVersion", "Invalid language version format"); + return SimpleLanguageVersion(major, minor, source); +} + +abstract class _SimpleLanguageVersionBase implements LanguageVersion { + int compareTo(LanguageVersion other) { + int result = major.compareTo(other.major); + if (result != 0) return result; + return minor.compareTo(other.minor); } } +class SimpleLanguageVersion extends _SimpleLanguageVersionBase { + final int major; + final int minor; + String /*?*/ _source; + SimpleLanguageVersion(this.major, this.minor, this._source); + + bool operator ==(Object other) => + other is LanguageVersion && major == other.major && minor == other.minor; + + int get hashCode => (major * 17 ^ minor * 37) & 0x3FFFFFFF; + + String toString() => _source ??= "$major.$minor"; +} + +class SimpleInvalidLanguageVersion extends _SimpleLanguageVersionBase + implements InvalidLanguageVersion { + final String _source; + SimpleInvalidLanguageVersion(this._source); + int get major => -1; + int get minor => -1; + + String toString() => _source; +} + abstract class PackageTree { + Iterable get allPackages; SimplePackage /*?*/ packageOf(Uri file); } @@ -210,13 +354,24 @@ class MutablePackageTree implements PackageTree { final List packages = []; Map /*?*/ _packageChildren; + Iterable get allPackages sync* { + for (var package in packages) yield package; + if (_packageChildren != null) { + for (var tree in _packageChildren.values) yield* tree.allPackages; + } + } + /// Tries to (add) `package` to the tree. /// - /// Throws [ConflictException] if the added package conflicts with an + /// Reports a [ConflictException] if the added package conflicts with an /// existing package. /// It conflicts if it has the same root path, or if the new package /// contains the existing package's package root. - void add(int start, SimplePackage package) { + /// + /// If a conflict is detected between [package] and a previous package, + /// then [onError] is called with a [ConflictException] object + /// and the [package] is not added to the tree. + void add(int start, SimplePackage package, void onError(Object error)) { var path = package.root.toString(); for (var childPackage in packages) { var childPath = childPackage.root.toString(); @@ -225,13 +380,15 @@ class MutablePackageTree implements PackageTree { if (_beginsWith(start, childPath, path)) { var childPathLength = childPath.length; if (path.length == childPathLength) { - throw ConflictException.root(package, childPackage); + onError(ConflictException.root(package, childPackage)); + return; } var childPackageRoot = childPackage.packageUriRoot.toString(); if (_beginsWith(childPathLength, childPackageRoot, path)) { - throw ConflictException.packageRoot(package, childPackage); + onError(ConflictException.packageRoot(package, childPackage)); + return; } - _treeOf(childPackage).add(childPathLength, package); + _treeOf(childPackage).add(childPathLength, package, onError); return; } } @@ -286,6 +443,8 @@ class MutablePackageTree implements PackageTree { class EmptyPackageTree implements PackageTree { const EmptyPackageTree(); + Iterable get allPackages => const Iterable.empty(); + SimplePackage packageOf(Uri file) => null; } diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 8108102bd..f56c91271 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -6,9 +6,6 @@ import "dart:convert"; import "dart:io"; import "dart:typed_data"; -import 'package:charcode/ascii.dart'; -import "package:path/path.dart" as p; - import "discovery.dart" show packageConfigJsonPath; import "errors.dart"; import "package_config_impl.dart"; @@ -45,41 +42,66 @@ const String _generatorVersionKey = "generatorVersion"; /// a `.packages` file and there is an available `package_config.json` file. /// /// The file must exist and be a normal file. -Future readAnyConfigFile(File file, bool preferNewest) async { - var bytes = await file.readAsBytes(); +Future readAnyConfigFile( + File file, bool preferNewest, void onError(Object error)) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } int firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { // Definitely not a JSON object, probably a .packages. if (preferNewest) { var alternateFile = File( - p.join(p.dirname(file.path), ".dart_tool", "package_config.json")); + pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); if (alternateFile.existsSync()) { - return parsePackageConfigBytes( - await alternateFile.readAsBytes(), alternateFile.uri); + Uint8List /*?*/ bytes; + try { + bytes = await alternateFile.readAsBytes(); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + if (bytes != null) { + return parsePackageConfigBytes(bytes, alternateFile.uri, onError); + } } } - return packages_file.parse(bytes, file.uri); + return packages_file.parse(bytes, file.uri, onError); } - return parsePackageConfigBytes(bytes, file.uri); + return parsePackageConfigBytes(bytes, file.uri, onError); } /// Like [readAnyConfigFile] but uses a URI and an optional loader. -Future readAnyConfigFileUri(Uri file, - Future loader(Uri uri) /*?*/, bool preferNewest) async { +Future readAnyConfigFileUri( + Uri file, + Future loader(Uri uri) /*?*/, + void onError(Object error), + bool preferNewest) async { if (file.isScheme("package")) { throw PackageConfigArgumentError( file, "file", "Must not be a package: URI"); } if (loader == null) { if (file.isScheme("file")) { - return readAnyConfigFile(File.fromUri(file), preferNewest); + return readAnyConfigFile(File.fromUri(file), preferNewest, onError); } loader = defaultLoader; } - var bytes = await loader(file); + Uint8List bytes; + try { + bytes = await loader(file); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } if (bytes == null) { - throw PackageConfigArgumentError( - file.toString(), "file", "File cannot be read"); + onError(PackageConfigArgumentError( + file.toString(), "file", "File cannot be read")); + return const SimplePackageConfig.empty(); } int firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { @@ -87,39 +109,59 @@ Future readAnyConfigFileUri(Uri file, if (preferNewest) { // Check if there is a package_config.json file. var alternateFile = file.resolveUri(packageConfigJsonPath); - var alternateBytes = await loader(alternateFile); + Uint8List alternateBytes; + try { + alternateBytes = await loader(alternateFile); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } if (alternateBytes != null) { - return parsePackageConfigBytes(alternateBytes, alternateFile); + return parsePackageConfigBytes(alternateBytes, alternateFile, onError); } } - return packages_file.parse(bytes, file); + return packages_file.parse(bytes, file, onError); } - return parsePackageConfigBytes(bytes, file); + return parsePackageConfigBytes(bytes, file, onError); } -Future readPackageConfigJsonFile(File file) async { +Future readPackageConfigJsonFile( + File file, void onError(Object error)) async { Uint8List bytes; try { bytes = await file.readAsBytes(); - } catch (_) { - return null; + } catch (error) { + onError(error); + return const SimplePackageConfig.empty(); } - return parsePackageConfigBytes(bytes, file.uri); + return parsePackageConfigBytes(bytes, file.uri, onError); } -Future readDotPackagesFile(File file) async { +Future readDotPackagesFile( + File file, void onError(Object error)) async { Uint8List bytes; try { bytes = await file.readAsBytes(); - } catch (_) { - return null; + } catch (error) { + onError(error); + return const SimplePackageConfig.empty(); } - return packages_file.parse(bytes, file.uri); + return packages_file.parse(bytes, file.uri, onError); } -PackageConfig parsePackageConfigBytes(Uint8List bytes, Uri file) { +final _jsonUtf8Decoder = json.fuse(utf8).decoder; + +PackageConfig parsePackageConfigBytes( + Uint8List bytes, Uri file, void onError(Object error)) { // TODO(lrn): Make this simpler. Maybe parse directly from bytes. - return parsePackageConfigJson(json.fuse(utf8).decode(bytes), file); + var jsonObject; + try { + jsonObject = _jsonUtf8Decoder.convert(bytes); + } on FormatException catch (e) { + onError(PackageConfigFormatException(e.message, e.source, e.offset)); + return const SimplePackageConfig.empty(); + } + return parsePackageConfigJson(jsonObject, file, onError); } /// Creates a [PackageConfig] from a parsed JSON-like object structure. @@ -144,7 +186,8 @@ PackageConfig parsePackageConfigBytes(Uint8List bytes, Uri file) { /// /// The [baseLocation] is used as base URI to resolve the "rootUri" /// URI referencestring. -PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { +PackageConfig parsePackageConfigJson( + dynamic json, Uri baseLocation, void onError(Object error)) { if (!baseLocation.hasScheme || baseLocation.isScheme("package")) { throw PackageConfigArgumentError(baseLocation.toString(), "baseLocation", "Must be an absolute non-package: URI"); @@ -168,27 +211,34 @@ PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { var message = "$name${packageName != null ? " of package $packageName" : ""}" " is not a JSON ${typeName()}"; - throw PackageConfigFormatException(message, value); + onError(PackageConfigFormatException(message, value)); + return null; } - Package parsePackage(Map entry) { + Package /*?*/ parsePackage(Map entry) { String /*?*/ name; String /*?*/ rootUri; String /*?*/ packageUri; String /*?*/ languageVersion; Map /*?*/ extraData; + bool hasName = false; + bool hasRoot = false; + bool hasVersion = false; entry.forEach((key, value) { switch (key) { case _nameKey: + hasName = true; name = checkType(value, _nameKey); break; case _rootUriKey: + hasRoot = true; rootUri = checkType(value, _rootUriKey, name); break; case _packageUriKey: packageUri = checkType(value, _packageUriKey, name); break; case _languageVersionKey: + hasVersion = true; languageVersion = checkType(value, _languageVersionKey, name); break; default: @@ -196,37 +246,61 @@ PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { break; } }); - if (name == null) { - throw PackageConfigFormatException("Missing name entry", entry); + if (!hasName) { + onError(PackageConfigFormatException("Missing name entry", entry)); } - if (rootUri == null) { - throw PackageConfigFormatException("Missing rootUri entry", entry); + if (!hasRoot) { + onError(PackageConfigFormatException("Missing rootUri entry", entry)); } + if (name == null || rootUri == null) return null; Uri root = baseLocation.resolve(rootUri); - Uri /*?*/ packageRoot = root; + if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/"); + Uri packageRoot = root; if (packageUri != null) packageRoot = root.resolve(packageUri); - try { - return SimplePackage(name, root, packageRoot, languageVersion, extraData); - } on ArgumentError catch (e) { - throw PackageConfigFormatException(e.message, e.invalidValue); + if (!packageRoot.path.endsWith("/")) { + packageRoot = packageRoot.replace(path: packageRoot.path + "/"); + } + + LanguageVersion /*?*/ version; + if (languageVersion != null) { + version = parseLanguageVersion(languageVersion, onError); + } else if (hasVersion) { + version = SimpleInvalidLanguageVersion("invalid"); } + + return SimplePackage.validate(name, root, packageRoot, version, extraData, + (error) { + if (error is ArgumentError) { + onError( + PackageConfigFormatException(error.message, error.invalidValue)); + } else { + onError(error); + } + }); } var map = checkType>(json, "value"); + if (map == null) return const SimplePackageConfig.empty(); Map /*?*/ extraData = null; List /*?*/ packageList; int /*?*/ configVersion; map.forEach((key, value) { switch (key) { case _configVersionKey: - configVersion = checkType(value, _configVersionKey); + configVersion = checkType(value, _configVersionKey) ?? 2; break; case _packagesKey: - var packageArray = checkType>(value, _packagesKey); + var packageArray = checkType>(value, _packagesKey) ?? []; var packages = []; for (var package in packageArray) { - packages.add(parsePackage( - checkType>(package, "package entry"))); + var packageMap = + checkType>(package, "package entry"); + if (packageMap != null) { + var entry = parsePackage(packageMap); + if (entry != null) { + packages.add(entry); + } + } } packageList = packages; break; @@ -236,22 +310,27 @@ PackageConfig parsePackageConfigJson(dynamic json, Uri baseLocation) { } }); if (configVersion == null) { - throw PackageConfigFormatException("Missing configVersion entry", json); + onError(PackageConfigFormatException("Missing configVersion entry", json)); + configVersion = 2; } - if (packageList == null) - throw PackageConfigFormatException("Missing packages list", json); - try { - return SimplePackageConfig(configVersion, packageList, extraData); - } on ArgumentError catch (e) { - throw PackageConfigFormatException(e.message, e.invalidValue); + if (packageList == null) { + onError(PackageConfigFormatException("Missing packages list", json)); + packageList = []; } + return SimplePackageConfig(configVersion, packageList, extraData, (error) { + if (error is ArgumentError) { + onError(PackageConfigFormatException(error.message, error.invalidValue)); + } else { + onError(error); + } + }); } Future writePackageConfigJson( PackageConfig config, Directory targetDirectory) async { // Write .dart_tool/package_config.json first. var file = - File(p.join(targetDirectory.path, ".dart_tool", "package_config.json")); + File(pathJoin(targetDirectory.path, ".dart_tool", "package_config.json")); var baseUri = file.uri; var extraData = config.extraData; var data = { @@ -263,8 +342,9 @@ Future writePackageConfigJson( _rootUriKey: relativizeUri(package.root, baseUri), if (package.root != package.packageUriRoot) _packageUriKey: relativizeUri(package.packageUriRoot, package.root), - if (package.languageVersion != null) - _languageVersionKey: package.languageVersion, + if (package.languageVersion != null && + package.languageVersion is! InvalidLanguageVersion) + _languageVersionKey: package.languageVersion.toString(), ...?_extractExtraData(package.extraData, _packageNames), } ], @@ -283,7 +363,7 @@ Future writePackageConfigJson( "${generated != null ? " on $generated" : ""}."; } } - file = File(p.join(targetDirectory.path, ".packages")); + file = File(pathJoin(targetDirectory.path, ".packages")); baseUri = file.uri; var buffer = StringBuffer(); packages_file.write(buffer, config, baseUri: baseUri, comment: comment); diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index ac57b4f15..475a782a2 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import "package_config_impl.dart"; -import "package:charcode/ascii.dart"; -import "util.dart" show isValidPackageName, relativizeUri; +import "util.dart"; import "errors.dart"; /// Parses a `.packages` file into a [PackageConfig]. @@ -25,16 +24,18 @@ import "errors.dart"; /// Returns a simple package configuration where each package's /// [Package.packageUriRoot] is the same as its [Package.root] /// and it has no [Package.languageVersion]. -PackageConfig parse(List source, Uri baseLocation) { +PackageConfig parse( + List source, Uri baseLocation, void onError(Object error)) { if (baseLocation.isScheme("package")) { - throw PackageConfigArgumentError( - baseLocation, "baseLocation", "Must not be a package: URI"); + onError(PackageConfigArgumentError( + baseLocation, "baseLocation", "Must not be a package: URI")); + return PackageConfig.empty; } int index = 0; List packages = []; Set packageNames = {}; while (index < source.length) { - bool isComment = false; + bool ignoreLine = false; int start = index; int separatorIndex = -1; int end = source.length; @@ -43,10 +44,14 @@ PackageConfig parse(List source, Uri baseLocation) { continue; } if (char == $colon) { - throw PackageConfigFormatException( - "Missing package name", source, index - 1); + onError(PackageConfigFormatException( + "Missing package name", source, index - 1)); + ignoreLine = true; // Ignore if package name is invalid. + } else { + ignoreLine = char == $hash; // Ignore if comment. } - isComment = char == $hash; + int queryStart = -1; + int fragmentStart = -1; while (index < source.length) { char = source[index++]; if (char == $colon && separatorIndex < 0) { @@ -54,40 +59,70 @@ PackageConfig parse(List source, Uri baseLocation) { } else if (char == $cr || char == $lf) { end = index - 1; break; + } else if (char == $question && queryStart < 0 && fragmentStart < 0) { + queryStart = index - 1; + } else if (char == $hash && fragmentStart < 0) { + fragmentStart = index - 1; } } - if (isComment) continue; + if (ignoreLine) continue; if (separatorIndex < 0) { - throw PackageConfigFormatException("No ':' on line", source, index - 1); + onError( + PackageConfigFormatException("No ':' on line", source, index - 1)); + continue; } var packageName = String.fromCharCodes(source, start, separatorIndex); - if (!isValidPackageName(packageName)) { - throw PackageConfigFormatException( - "Not a valid package name", packageName, 0); + int invalidIndex = checkPackageName(packageName); + if (invalidIndex >= 0) { + onError(PackageConfigFormatException( + "Not a valid package name", source, start + invalidIndex)); + continue; + } + if (queryStart >= 0) { + onError(PackageConfigFormatException( + "Location URI must not have query", source, queryStart)); + end = queryStart; + } else if (fragmentStart >= 0) { + onError(PackageConfigFormatException( + "Location URI must not have fragment", source, fragmentStart)); + end = fragmentStart; } var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); - Uri packageLocation = baseLocation.resolve(packageValue); - if (packageLocation.isScheme("package")) { - throw PackageConfigFormatException( - "Package URI as location for package", source, separatorIndex + 1); + Uri packageLocation; + try { + packageLocation = baseLocation.resolve(packageValue); + } on FormatException catch (e) { + onError(PackageConfigFormatException.from(e)); + continue; } - if (packageLocation.hasQuery || packageLocation.hasFragment) { - throw PackageConfigFormatException( - "Location URI must not have query or fragment", source, start); + if (packageLocation.isScheme("package")) { + onError(PackageConfigFormatException( + "Package URI as location for package", source, separatorIndex + 1)); + continue; } if (!packageLocation.path.endsWith('/')) { packageLocation = packageLocation.replace(path: packageLocation.path + "/"); } if (packageNames.contains(packageName)) { - throw PackageConfigFormatException( - "Same package name occured more than once", source, start); + onError(PackageConfigFormatException( + "Same package name occured more than once", source, start)); + continue; + } + var package = SimplePackage.validate( + packageName, packageLocation, packageLocation, null, null, (error) { + if (error is ArgumentError) { + onError(PackageConfigFormatException(error.message, source)); + } else { + onError(error); + } + }); + if (package != null) { + packages.add(package); + packageNames.add(packageName); } - packages.add(SimplePackage( - packageName, packageLocation, packageLocation, null, null)); - packageNames.add(packageName); } - return SimplePackageConfig(1, packages, null); + return SimplePackageConfig(1, packages, null, onError); } /// Writes the configuration to a [StringSink]. @@ -137,7 +172,7 @@ void write(StringSink output, PackageConfig config, } output.write(packageName); output.write(':'); - // If baseUri provided, make uri relative. + // If baseUri is provided, make the URI relative to baseUri. if (baseUri != null) { uri = relativizeUri(uri, baseUri); } diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 25d7b89e4..2609a2f8a 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -8,8 +8,6 @@ library package_config.util; import 'dart:io'; import 'dart:typed_data'; -import "package:charcode/ascii.dart"; - import "errors.dart"; // All ASCII characters that are valid in a package name, with space @@ -46,6 +44,11 @@ int checkPackageName(String string) { } /// Validate that a [Uri] is a valid `package:` URI. +/// +/// Used to validate user input. +/// +/// Returns the package name extracted from the package URI, +/// which is the path segment between `package:` and the first `/`. String checkValidPackageUri(Uri packageUri, String name) { if (packageUri.scheme != "package") { throw PackageConfigArgumentError(packageUri, name, "Not a package: URI"); @@ -100,65 +103,16 @@ String checkValidPackageUri(Uri packageUri, String name) { return packageName; } -/// Checks whether [version] is a valid Dart language version string. -/// -/// The format is (as RegExp) `^(0|[1-9]\d+)\.(0|[1-9]\d+)$`. -/// -/// Returns the position of the first invalid character, or -1 if -/// the string is valid. -/// If the string is terminated early, the result is the length of the string. -int checkValidVersionNumber(String version) { - if (version == null) { - return 0; - } - int index = 0; - int dotsSeen = 0; - outer: - for (;;) { - // Check for numeral. - if (index == version.length) return index; - int char = version.codeUnitAt(index++); - int digit = char ^ 0x30; - if (digit != 0) { - if (digit < 9) { - while (index < version.length) { - char = version.codeUnitAt(index++); - digit = char ^ 0x30; - if (digit < 9) continue; - if (char == 0x2e /*.*/) { - if (dotsSeen > 0) return index - 1; - dotsSeen = 1; - continue outer; - } - return index - 1; - } - if (dotsSeen > 0) return -1; - return index; - } - return index - 1; - } - // Leading zero means numeral is over. - if (index >= version.length) { - if (dotsSeen > 0) return -1; - return index; - } - if (dotsSeen > 0) return index; - char = version.codeUnitAt(index++); - if (char != 0x2e /*.*/) return index - 1; - } -} - /// Checks whether URI is just an absolute directory. /// /// * It must have a scheme. /// * It must not have a query or fragment. -/// * The path must start and end with `/`. +/// * The path must end with `/`. bool isAbsoluteDirectoryUri(Uri uri) { if (uri.hasQuery) return false; if (uri.hasFragment) return false; if (!uri.hasScheme) return false; var path = uri.path; - if (!path.startsWith("/")) return false; if (!path.endsWith("/")) return false; return true; } @@ -302,3 +256,63 @@ Future _httpGet(Uri uri) async { } return result; } + +/// The file name of a path. +/// +/// The file name is everything after the last occurrence of +/// [Platform.pathSeparator]. +String fileName(String path) { + var separator = Platform.pathSeparator; + int lastSeparator = path.lastIndexOf(separator); + if (lastSeparator < 0) return path; + return path.substring(lastSeparator + separator.length); +} + +/// The file name of a path. +/// +/// The file name is everything before the last occurrence of +/// [Platform.pathSeparator]. +String dirName(String path) { + var separator = Platform.pathSeparator; + int lastSeparator = path.lastIndexOf(separator); + if (lastSeparator < 0) return ""; + return path.substring(0, lastSeparator); +} + +/// Join path parts with the [Platform.pathSeparator]. +String pathJoin(String part1, String part2, [String part3]) { + var separator = Platform.pathSeparator; + if (part3 == null) { + return "$part1$separator$part2"; + } + return "$part1$separator$part2$separator$part3"; +} + +/// Join an unknown number of path parts with [Platform.pathSeparator]. +String pathJoinAll(Iterable parts) => + parts.join(Platform.pathSeparator); + +// Character constants used by this package. +/// "Line feed" control character. +const int $lf = 0x0a; + +/// "Carriage return" control character. +const int $cr = 0x0d; + +/// Space character. +const int $space = 0x20; + +/// Character `#`. +const int $hash = 0x23; + +/// Character `.`. +const int $dot = 0x2e; + +/// Character `:`. +const int $colon = 0x3a; + +/// Character `?`. +const int $question = 0x3f; + +/// Character `{`. +const int $lbrace = 0x7b; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 66aeb7858..7f47d2e2c 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.0 +version: 3.0.0-dev description: Support for working with Package Configuration files. author: Dart Team homepage: https://github.com/dart-lang/package_config @@ -7,9 +7,5 @@ homepage: https://github.com/dart-lang/package_config environment: sdk: '>=2.7.0 <3.0.0' -dependencies: - charcode: ^1.1.0 - path: ^1.0.0 - dev_dependencies: test: ^1.3.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 3256187d2..23efc6741 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -114,36 +114,92 @@ main() { expect(config, null); }); - fileTest("invalid .packages", { - ".packages": "not a .packages file", - }, (Directory directory) { - expect(() => findPackageConfig(directory), - throwsA(TypeMatcher())); - }); + group("throws", () { + fileTest("invalid .packages", { + ".packages": "not a .packages file", + }, (Directory directory) { + expect(findPackageConfig(directory), + throwsA(TypeMatcher())); + }); - fileTest("invalid .packages as JSON", { - ".packages": packageConfigFile, - }, (Directory directory) { - expect(() => findPackageConfig(directory), - throwsA(TypeMatcher())); - }); + fileTest("invalid .packages as JSON", { + ".packages": packageConfigFile, + }, (Directory directory) { + expect(findPackageConfig(directory), + throwsA(TypeMatcher())); + }); - fileTest("invalid .packages", { - ".dart_tool": { - "package_config.json": "not a JSON file", - } - }, (Directory directory) { - expect(() => findPackageConfig(directory), - throwsA(TypeMatcher())); + fileTest("invalid .packages", { + ".dart_tool": { + "package_config.json": "not a JSON file", + } + }, (Directory directory) { + expect(findPackageConfig(directory), + throwsA(TypeMatcher())); + }); + + fileTest("invalid .packages as INI", { + ".dart_tool": { + "package_config.json": packagesFile, + } + }, (Directory directory) { + expect(findPackageConfig(directory), + throwsA(TypeMatcher())); + }); }); - fileTest("invalid .packages as INI", { - ".dart_tool": { - "package_config.json": packagesFile, - } - }, (Directory directory) { - expect(() => findPackageConfig(directory), - throwsA(TypeMatcher())); + group("handles error", () { + fileTest("invalid .packages", { + ".packages": "not a .packages file", + }, (Directory directory) async { + bool hadError = false; + await findPackageConfig(directory, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); + + fileTest("invalid .packages as JSON", { + ".packages": packageConfigFile, + }, (Directory directory) async { + bool hadError = false; + await findPackageConfig(directory, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); + + fileTest("invalid package_config not JSON", { + ".dart_tool": { + "package_config.json": "not a JSON file", + } + }, (Directory directory) async { + bool hadError = false; + await findPackageConfig(directory, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); + + fileTest("invalid package config as INI", { + ".dart_tool": { + "package_config.json": packagesFile, + } + }, (Directory directory) async { + bool hadError = false; + await findPackageConfig(directory, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); }); }); @@ -226,6 +282,17 @@ main() { throwsA(TypeMatcher())); }); + fileTest("no config found, handled", {}, (Directory directory) async { + File file = dirFile(directory, "anyname"); + bool hadError = false; + await loadPackageConfig(file, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); + fileTest("specified file syntax error", { "anyname": "syntax error", }, (Directory directory) { diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 8ad428ac0..081ec608f 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -4,6 +4,8 @@ library package_config.discovery_test; +import 'dart:io'; + import "package:test/test.dart"; import "package:package_config/package_config.dart"; @@ -219,7 +221,20 @@ main() { loaderTest("no config found", {}, (Uri directory, loader) { Uri file = directory.resolve("anyname"); expect(() => loadPackageConfigUri(file, loader: loader), - throwsArgumentError); + throwsA(isA())); + }); + + loaderTest("no config found, handle error", {}, + (Uri directory, loader) async { + Uri file = directory.resolve("anyname"); + bool hadError = false; + await loadPackageConfigUri(file, + loader: loader, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); }); loaderTest("specified file syntax error", { @@ -230,6 +245,20 @@ main() { throwsFormatException); }); + loaderTest("specified file syntax error", { + "anyname": "syntax error", + }, (Uri directory, loader) async { + Uri file = directory.resolve("anyname"); + bool hadError = false; + await loadPackageConfigUri(file, + loader: loader, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); + }); + // Find package_config.json in subdir even if initial file syntax error. loaderTest("specified file syntax error", { "anyname": "syntax error", @@ -246,10 +275,16 @@ main() { // A file starting with `{` is a package_config.json file. loaderTest("file syntax error with {", { ".packages": "{syntax error", - }, (Uri directory, loader) { + }, (Uri directory, loader) async { Uri file = directory.resolve(".packages"); - expect(() => loadPackageConfigUri(file, loader: loader), - throwsFormatException); + var hadError = false; + await loadPackageConfigUri(file, + loader: loader, + onError: expectAsync1((error) { + hadError = true; + expect(error, isA()); + }, max: -1)); + expect(hadError, true); }); }); } diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 3d1a20e4a..d9430953c 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -6,10 +6,13 @@ import "dart:convert"; import "package:test/test.dart"; +import "package:package_config/package_config.dart"; import "package:package_config/src/packages_file.dart" as packages; import "package:package_config/src/package_config_json.dart"; import "src/util.dart"; +void throwError(Object error) => throw error; + void main() { group(".packages", () { test("valid", () { @@ -17,8 +20,8 @@ void main() { "foo:file:///foo/lib/\n" "bar:/bar/lib/\n" "baz:lib/\n"; - var result = packages.parse( - utf8.encode(packagesFile), Uri.parse("file:///tmp/file.dart")); + var result = packages.parse(utf8.encode(packagesFile), + Uri.parse("file:///tmp/file.dart"), throwError); expect(result.version, 1); expect({for (var p in result.packages) p.name}, {"foo", "bar", "baz"}); expect(result.resolve(pkg("foo", "foo.dart")), @@ -37,8 +40,8 @@ void main() { test("valid empty", () { var packagesFile = "# Generated by pub yadda yadda\n"; - var result = - packages.parse(utf8.encode(packagesFile), Uri.file("/tmp/file.dart")); + var result = packages.parse( + utf8.encode(packagesFile), Uri.file("/tmp/file.dart"), throwError); expect(result.version, 1); expect({for (var p in result.packages) p.name}, {}); }); @@ -47,9 +50,18 @@ void main() { var baseFile = Uri.file("/tmp/file.dart"); testThrows(String name, String content) { test(name, () { - expect(() => packages.parse(utf8.encode(content), baseFile), + expect( + () => packages.parse(utf8.encode(content), baseFile, throwError), throwsA(TypeMatcher())); }); + test(name + ", handle error", () { + bool hadError = false; + packages.parse(utf8.encode(content), baseFile, (error) { + hadError = true; + expect(error, isA()); + }); + expect(hadError, true); + }); } testThrows("repeated package name", "foo:lib/\nfoo:lib\n"); @@ -81,12 +93,17 @@ void main() { "name": "bar", "rootUri": "/bar/", "packageUri": "lib/", - "languageVersion": "100.100" + "languageVersion": "9999.9999" }, { "name": "baz", "rootUri": "../", "packageUri": "lib/" + }, + { + "name": "noslash", + "rootUri": "../noslash", + "packageUri": "lib" } ], "generator": "pub", @@ -94,9 +111,10 @@ void main() { } """; var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), - Uri.parse("file:///tmp/.dart_tool/file.dart")); + Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); - expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); + expect({for (var p in config.packages) p.name}, + {"foo", "bar", "baz", "noslash"}); expect(config.resolve(pkg("foo", "foo.dart")), Uri.parse("file:///foo/lib/foo.dart")); @@ -109,14 +127,14 @@ void main() { expect(foo, isNotNull); expect(foo.root, Uri.parse("file:///foo/")); expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); - expect(foo.languageVersion, "2.5"); + expect(foo.languageVersion, LanguageVersion(2, 5)); expect(foo.extraData, {"nonstandard": true}); var bar = config["bar"]; expect(bar, isNotNull); expect(bar.root, Uri.parse("file:///bar/")); expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/")); - expect(bar.languageVersion, "100.100"); + expect(bar.languageVersion, LanguageVersion(9999, 9999)); expect(bar.extraData, null); var baz = config["baz"]; @@ -125,6 +143,13 @@ void main() { expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/")); expect(baz.languageVersion, null); + // No slash after root or package root. One is inserted. + var noslash = config["noslash"]; + expect(noslash, isNotNull); + expect(noslash.root, Uri.parse("file:///tmp/noslash/")); + expect(noslash.packageUriRoot, Uri.parse("file:///tmp/noslash/lib/")); + expect(noslash.languageVersion, null); + expect(config.extraData, { "generator": "pub", "other": [42] @@ -146,7 +171,7 @@ void main() { }, { "packageUri": "lib/", - "languageVersion": "100.100", + "languageVersion": "9999.9999", "rootUri": "/bar/", "name": "bar" }, @@ -160,7 +185,7 @@ void main() { } """; var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), - Uri.parse("file:///tmp/.dart_tool/file.dart")); + Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); @@ -184,7 +209,7 @@ void main() { var root = '"rootUri":"/foo/"'; test("minimal", () { var config = parsePackageConfigBytes(utf8.encode("{$cfg,$pkgs}"), - Uri.parse("file:///tmp/.dart_tool/file.dart")); + Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); expect(config.packages, isEmpty); }); @@ -193,7 +218,8 @@ void main() { // are optional. var config = parsePackageConfigBytes( utf8.encode('{$cfg,"packages":[{$name,$root}]}'), - Uri.parse("file:///tmp/.dart_tool/file.dart")); + Uri.parse("file:///tmp/.dart_tool/file.dart"), + throwError); expect(config.version, 2); expect(config.packages.first.name, "foo"); }); @@ -208,8 +234,8 @@ void main() { {"name": "qux", "rootUri": "/foo/qux/", "packageUri": "lib/"}, ] })); - var config = parsePackageConfigBytes( - configBytes, Uri.parse("file:///tmp/.dart_tool/file.dart")); + var config = parsePackageConfigBytes(configBytes, + Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart")).name, "foo"); @@ -232,12 +258,9 @@ void main() { group("invalid", () { testThrows(String name, String source) { test(name, () { - if (name == "inside lib") { - print(name); - } expect( () => parsePackageConfigBytes(utf8.encode(source), - Uri.parse("file:///tmp/.dart_tool/file.dart")), + Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError), throwsA(TypeMatcher())); }); } diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index ec4e5e8bc..95670bdbb 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -6,8 +6,8 @@ import 'dart:convert'; import "dart:io"; import 'dart:typed_data'; -import "package:path/path.dart" as path; import "package:test/test.dart"; +import "package:package_config/src/util.dart"; /// Creates a directory structure from [description] and runs [fileTest]. /// @@ -46,7 +46,7 @@ Directory createTestFiles(Map description) { // Creates temporary files in the target directory. void _createFiles(Directory target, Map description) { description.forEach((name, content) { - var entryName = path.join(target.path, "$name"); + var entryName = pathJoin(target.path, "$name"); if (content is Map) { _createFiles(Directory(entryName)..createSync(), content); } else { @@ -57,11 +57,11 @@ void _createFiles(Directory target, Map description) { /// Creates a [Directory] for a subdirectory of [parent]. Directory subdir(Directory parent, String dirName) => - Directory(path.joinAll([parent.path, ...dirName.split("/")])); + Directory(pathJoinAll([parent.path, ...dirName.split("/")])); /// Creates a [File] for an entry in the [directory] directory. File dirFile(Directory directory, String fileName) => - File(path.join(directory.path, fileName)); + File(pathJoin(directory.path, fileName)); /// Creates a package: URI. Uri pkg(String packageName, String packagePath) { From 917abca9660d8e75ffda2cb5f2f3e0d0648fef4c Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 11 Feb 2020 14:28:07 +0100 Subject: [PATCH 132/281] Fix doc and bug in util.dart --- pkgs/package_config/lib/src/util.dart | 34 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 2609a2f8a..f39027d00 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -260,7 +260,8 @@ Future _httpGet(Uri uri) async { /// The file name of a path. /// /// The file name is everything after the last occurrence of -/// [Platform.pathSeparator]. +/// [Platform.pathSeparator], or the entire string if no +/// path separator occurs in the string. String fileName(String path) { var separator = Platform.pathSeparator; int lastSeparator = path.lastIndexOf(separator); @@ -268,10 +269,11 @@ String fileName(String path) { return path.substring(lastSeparator + separator.length); } -/// The file name of a path. +/// The directory name of a path. /// -/// The file name is everything before the last occurrence of -/// [Platform.pathSeparator]. +/// The directory name is everything before the last occurrence of +/// [Platform.pathSeparator], or the empty string if no +/// path separator occurs in the string. String dirName(String path) { var separator = Platform.pathSeparator; int lastSeparator = path.lastIndexOf(separator); @@ -280,17 +282,33 @@ String dirName(String path) { } /// Join path parts with the [Platform.pathSeparator]. +/// +/// If a part ends with a path separator, then no extra separator is +/// inserted. String pathJoin(String part1, String part2, [String part3]) { var separator = Platform.pathSeparator; + String separator1 = part1.endsWith(separator) ? "" : separator; if (part3 == null) { - return "$part1$separator$part2"; + return "$part1$separator1$part2"; } - return "$part1$separator$part2$separator$part3"; + String separator2 = part2.endsWith(separator) ? "" : separator; + return "$part1$separator1$part2$separator2$part3"; } /// Join an unknown number of path parts with [Platform.pathSeparator]. -String pathJoinAll(Iterable parts) => - parts.join(Platform.pathSeparator); +/// +/// If a part ends with a path separator, then no extra separator is +/// inserted. +String pathJoinAll(Iterable parts) { + var buffer = StringBuffer(); + String separator = ""; + for (var part in parts) { + buffer..write(separator)..write(part); + separator = + part.endsWith(Platform.pathSeparator) ? "" : Platform.pathSeparator; + } + return buffer.toString(); +} // Character constants used by this package. /// "Line feed" control character. From 0117f2517cb08173b4712f0eb937c629e111c02e Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 21 Feb 2020 09:36:22 +0100 Subject: [PATCH 133/281] Support the new package_config.json file format. Add support for new format. Retains, but deprecates, the existing functionality. A later 2.0 release will remove support for the old file format. --- pkgs/package_config/CHANGELOG.md | 16 +- pkgs/package_config/README.md | 13 + pkgs/package_config/analysis_options.yaml | 11 + pkgs/package_config/lib/discovery.dart | 227 ++++++++++++ .../lib/discovery_analysis.dart | 167 +++++++++ pkgs/package_config/lib/package_config.dart | 10 +- .../lib/package_config_types.dart | 11 + pkgs/package_config/lib/packages.dart | 96 +++++ pkgs/package_config/lib/packages_file.dart | 232 +++++++++++++ pkgs/package_config/lib/src/discovery.dart | 2 + .../lib/src/package_config.dart | 109 +++++- .../lib/src/package_config_impl.dart | 64 +++- .../lib/src/package_config_io.dart | 155 +++++++++ .../lib/src/package_config_json.dart | 220 ++++-------- .../package_config/lib/src/packages_file.dart | 22 +- .../package_config/lib/src/packages_impl.dart | 128 +++++++ .../lib/src/packages_io_impl.dart | 46 +++ pkgs/package_config/lib/src/util.dart | 49 +-- pkgs/package_config/pubspec.yaml | 6 +- pkgs/package_config/test/discovery_test.dart | 64 ++-- .../test/discovery_uri_test.dart | 60 ++-- pkgs/package_config/test/legacy/all.dart | 20 ++ .../test/legacy/discovery_analysis_test.dart | 127 +++++++ .../test/legacy/discovery_test.dart | 328 ++++++++++++++++++ .../test/legacy/parse_test.dart | 246 +++++++++++++ .../test/legacy/parse_write_test.dart | 133 +++++++ pkgs/package_config/test/parse_test.dart | 85 ++++- pkgs/package_config/test/src/util.dart | 8 +- 28 files changed, 2340 insertions(+), 315 deletions(-) create mode 100644 pkgs/package_config/analysis_options.yaml create mode 100644 pkgs/package_config/lib/discovery.dart create mode 100644 pkgs/package_config/lib/discovery_analysis.dart create mode 100644 pkgs/package_config/lib/package_config_types.dart create mode 100644 pkgs/package_config/lib/packages.dart create mode 100644 pkgs/package_config/lib/packages_file.dart create mode 100644 pkgs/package_config/lib/src/package_config_io.dart create mode 100644 pkgs/package_config/lib/src/packages_impl.dart create mode 100644 pkgs/package_config/lib/src/packages_io_impl.dart create mode 100644 pkgs/package_config/test/legacy/all.dart create mode 100644 pkgs/package_config/test/legacy/discovery_analysis_test.dart create mode 100644 pkgs/package_config/test/legacy/discovery_test.dart create mode 100644 pkgs/package_config/test/legacy/parse_test.dart create mode 100644 pkgs/package_config/test/legacy/parse_write_test.dart diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 317184075..c6caf4d6e 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,17 +1,9 @@ -## 3.0.0 - -- Make the language version be represented as a `LanguageVersion` class - instead of a string. -- Made error handling interceptable. Passing an `onError` handler - makes the parsers attempt to do a best-effort error correction after - detecting an error. -- Do not require root URIs to have paths starting with `/`. That - only makes sense for `file` or `http`, and they enforce it anyway. -- Fixed bug in language version validation not accepting the digit `9`. - -## 2.0.0 +## 1.9.0 - Based on new JSON file format with more content. +- This version includes all the new functionality intended for a 2.0.0 + version, as well as the, now deprecated, version 1 functionality. + When we release 2.0.0, the deprectated functionality will be removed. ## 1.2.0 diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 45791aaf3..ec51f6ea7 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -3,6 +3,19 @@ Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). +The primary libraries are +* `package_config.dart`: + Defines the `PackageConfig` class and other types needed to use + package configurations. + +* `package_config_discovery.dart`: + Provides functions for reading configurations from files, + and writing them back out. + +The package includes deprecated backwards compatible functionality to +work with the `.packages` file. This functionality will not be maintained, +and will be removed in a future version of this package. + [![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) ## Features and bugs diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml new file mode 100644 index 000000000..82c00e5c8 --- /dev/null +++ b/pkgs/package_config/analysis_options.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2020, 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. + +include: package:pedantic/analysis_options.yaml +analyzer: + errors: + annotate_overrides: ignore + curly_braces_in_flow_control_structures: ignore + prefer_single_quotes: ignore + use_function_type_syntax_for_parameters: ignore diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart new file mode 100644 index 000000000..a2f53c0e6 --- /dev/null +++ b/pkgs/package_config/lib/discovery.dart @@ -0,0 +1,227 @@ +// Copyright (c) 2015, 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. + +@Deprecated("Use the package_config.json based API") +library package_config.discovery; + +import "dart:async"; +import "dart:io"; +import "dart:typed_data" show Uint8List; + +import "package:path/path.dart" as path; + +import "packages.dart"; +import "packages_file.dart" as pkgfile show parse; +import "src/packages_impl.dart"; +import "src/packages_io_impl.dart"; + +/// Reads a package resolution file and creates a [Packages] object from it. +/// +/// The [packagesFile] must exist and be loadable. +/// Currently that means the URI must have a `file`, `http` or `https` scheme, +/// and that the file can be loaded and its contents parsed correctly. +/// +/// If the [loader] is provided, it is used to fetch non-`file` URIs, and +/// it can support other schemes or set up more complex HTTP requests. +/// +/// This function can be used to load an explicitly configured package +/// resolution file, for example one specified using a `--packages` +/// command-line parameter. +Future loadPackagesFile(Uri packagesFile, + {Future> loader(Uri uri)}) async { + Packages parseBytes(List bytes) { + return MapPackages(pkgfile.parse(bytes, packagesFile)); + } + + if (packagesFile.scheme == "file") { + return parseBytes(await File.fromUri(packagesFile).readAsBytes()); + } + if (loader == null) { + return parseBytes(await _httpGet(packagesFile)); + } + return parseBytes(await loader(packagesFile)); +} + +/// Create a [Packages] object for a package directory. +/// +/// The [packagesDir] URI should refer to a directory. +/// Package names are resolved as relative to sub-directories of the +/// package directory. +/// +/// This function can be used for explicitly configured package directories, +/// for example one specified using a `--package-root` comand-line parameter. +Packages getPackagesDirectory(Uri packagesDir) { + if (packagesDir.scheme == "file") { + return FilePackagesDirectoryPackages(Directory.fromUri(packagesDir)); + } + if (!packagesDir.path.endsWith('/')) { + packagesDir = packagesDir.replace(path: packagesDir.path + '/'); + } + return NonFilePackagesDirectoryPackages(packagesDir); +} + +/// Discover the package configuration for a Dart script. +/// +/// The [baseUri] points to either the Dart script or its directory. +/// A package resolution strategy is found by going through the following steps, +/// and stopping when something is found. +/// +/// * Check if a `.packages` file exists in the same directory. +/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory +/// in the same directory, and resolve packages relative to that. +/// * If `baseUri`'s scheme *is* `file`: +/// * Check if a `packages` directory exists. +/// * Otherwise check each successive parent directory of `baseUri` for a +/// `.packages` file. +/// +/// If any of these tests succeed, a `Packages` class is returned. +/// Returns the constant [noPackages] if no resolution strategy is found. +/// +/// This function currently only supports `file`, `http` and `https` URIs. +/// It needs to be able to load a `.packages` file from the URI, so only +/// recognized schemes are accepted. +/// +/// To support other schemes, or more complex HTTP requests, +/// an optional [loader] function can be supplied. +/// It's called to load the `.packages` file for a non-`file` scheme. +/// The loader function returns the *contents* of the file +/// identified by the URI it's given. +/// The content should be a UTF-8 encoded `.packages` file, and must return an +/// error future if loading fails for any reason. +Future findPackages(Uri baseUri, + {Future> loader(Uri unsupportedUri)}) { + if (baseUri.scheme == "file") { + return Future.sync(() => findPackagesFromFile(baseUri)); + } else if (loader != null) { + return findPackagesFromNonFile(baseUri, loader: loader); + } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { + return findPackagesFromNonFile(baseUri, loader: _httpGet); + } else { + return Future.value(Packages.noPackages); + } +} + +/// Find the location of the package resolution file/directory for a Dart file. +/// +/// Checks for a `.packages` file in the [workingDirectory]. +/// If not found, checks for a `packages` directory in the same directory. +/// If still not found, starts checking parent directories for +/// `.packages` until reaching the root directory. +/// +/// Returns a [File] object of a `.packages` file if one is found, or a +/// [Directory] object for the `packages/` directory if that is found. +FileSystemEntity _findPackagesFile(String workingDirectory) { + var dir = Directory(workingDirectory); + if (!dir.isAbsolute) dir = dir.absolute; + if (!dir.existsSync()) { + throw ArgumentError.value( + workingDirectory, "workingDirectory", "Directory does not exist."); + } + File checkForConfigFile(Directory directory) { + assert(directory.isAbsolute); + var file = File(path.join(directory.path, ".packages")); + if (file.existsSync()) return file; + return null; + } + + // Check for $cwd/.packages + var packagesCfgFile = checkForConfigFile(dir); + if (packagesCfgFile != null) return packagesCfgFile; + // Check for $cwd/packages/ + var packagesDir = Directory(path.join(dir.path, "packages")); + if (packagesDir.existsSync()) return packagesDir; + // Check for cwd(/..)+/.packages + var parentDir = dir.parent; + while (parentDir.path != dir.path) { + packagesCfgFile = checkForConfigFile(parentDir); + if (packagesCfgFile != null) break; + dir = parentDir; + parentDir = dir.parent; + } + return packagesCfgFile; +} + +/// Finds a package resolution strategy for a local Dart script. +/// +/// The [fileBaseUri] points to either a Dart script or the directory of the +/// script. The `fileBaseUri` must be a `file:` URI. +/// +/// This function first tries to locate a `.packages` file in the `fileBaseUri` +/// directory. If that is not found, it instead checks for the presence of +/// a `packages/` directory in the same place. +/// If that also fails, it starts checking parent directories for a `.packages` +/// file, and stops if it finds it. +/// Otherwise it gives up and returns [Packages.noPackages]. +Packages findPackagesFromFile(Uri fileBaseUri) { + var baseDirectoryUri = fileBaseUri; + if (!fileBaseUri.path.endsWith('/')) { + baseDirectoryUri = baseDirectoryUri.resolve("."); + } + var baseDirectoryPath = baseDirectoryUri.toFilePath(); + var location = _findPackagesFile(baseDirectoryPath); + if (location == null) return Packages.noPackages; + if (location is File) { + var fileBytes = location.readAsBytesSync(); + var map = pkgfile.parse(fileBytes, Uri.file(location.path)); + return MapPackages(map); + } + assert(location is Directory); + return FilePackagesDirectoryPackages(location); +} + +/// Finds a package resolution strategy for a Dart script. +/// +/// The [nonFileUri] points to either a Dart script or the directory of the +/// script. +/// The [nonFileUri] should not be a `file:` URI since the algorithm for +/// finding a package resolution strategy is more elaborate for `file:` URIs. +/// In that case, use [findPackagesFromFile]. +/// +/// This function first tries to locate a `.packages` file in the [nonFileUri] +/// directory. If that is not found, it instead assumes a `packages/` directory +/// in the same place. +/// +/// By default, this function only works for `http:` and `https:` URIs. +/// To support other schemes, a loader must be provided, which is used to +/// try to load the `.packages` file. The loader should return the contents +/// of the requested `.packages` file as bytes, which will be assumed to be +/// UTF-8 encoded. +Future findPackagesFromNonFile(Uri nonFileUri, + {Future> loader(Uri name)}) async { + loader ??= _httpGet; + var packagesFileUri = nonFileUri.resolve(".packages"); + + try { + var fileBytes = await loader(packagesFileUri); + var map = pkgfile.parse(fileBytes, packagesFileUri); + return MapPackages(map); + } catch (_) { + // Didn't manage to load ".packages". Assume a "packages/" directory. + var packagesDirectoryUri = nonFileUri.resolve("packages/"); + return NonFilePackagesDirectoryPackages(packagesDirectoryUri); + } +} + +/// Fetches a file over http. +Future> _httpGet(Uri uri) async { + var client = HttpClient(); + var request = await client.getUrl(uri); + var response = await request.close(); + if (response.statusCode != HttpStatus.ok) { + throw HttpException('${response.statusCode} ${response.reasonPhrase}', + uri: uri); + } + var splitContent = await response.toList(); + var totalLength = 0; + for (var list in splitContent) { + totalLength += list.length; + } + var result = Uint8List(totalLength); + var offset = 0; + for (var contentPart in splitContent) { + result.setRange(offset, offset + contentPart.length, contentPart); + offset += contentPart.length; + } + return result; +} diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart new file mode 100644 index 000000000..2af07292e --- /dev/null +++ b/pkgs/package_config/lib/discovery_analysis.dart @@ -0,0 +1,167 @@ +// Copyright (c) 2015, 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. + +/// Analyse a directory structure and find packages resolvers for each +/// sub-directory. +/// +/// The resolvers are generally the same that would be found by using +/// the `discovery.dart` library on each sub-directory in turn, +/// but more efficiently and with some heuristics for directories that +/// wouldn't otherwise have a package resolution strategy, or that are +/// determined to be "package directories" themselves. +@Deprecated("Use the package_config.json based API") +library package_config.discovery_analysis; + +import "dart:collection" show HashMap; +import "dart:io" show File, Directory; + +import "package:path/path.dart" as path; + +import "packages.dart"; +import "packages_file.dart" as pkgfile; +import "src/packages_impl.dart"; +import "src/packages_io_impl.dart"; + +/// Associates a [Packages] package resolution strategy with a directory. +/// +/// The package resolution applies to the directory and any sub-directory +/// that doesn't have its own overriding child [PackageContext]. +abstract class PackageContext { + /// The directory that introduced the [packages] resolver. + Directory get directory; + + /// A [Packages] resolver that applies to the directory. + /// + /// Introduced either by a `.packages` file or a `packages/` directory. + Packages get packages; + + /// Child contexts that apply to sub-directories of [directory]. + List get children; + + /// Look up the [PackageContext] that applies to a specific directory. + /// + /// The directory must be inside [directory]. + PackageContext operator [](Directory directory); + + /// A map from directory to package resolver. + /// + /// Has an entry for this package context and for each child context + /// contained in this one. + Map asMap(); + + /// Analyze [directory] and sub-directories for package resolution strategies. + /// + /// Returns a mapping from sub-directories to [Packages] objects. + /// + /// The analysis assumes that there are no `.packages` files in a parent + /// directory of `directory`. If there is, its corresponding `Packages` object + /// should be provided as `root`. + static PackageContext findAll(Directory directory, + {Packages root = Packages.noPackages}) { + if (!directory.existsSync()) { + throw ArgumentError("Directory not found: $directory"); + } + var contexts = []; + void findRoots(Directory directory) { + Packages packages; + List oldContexts; + var packagesFile = File(path.join(directory.path, ".packages")); + if (packagesFile.existsSync()) { + packages = _loadPackagesFile(packagesFile); + oldContexts = contexts; + contexts = []; + } else { + var packagesDir = Directory(path.join(directory.path, "packages")); + if (packagesDir.existsSync()) { + packages = FilePackagesDirectoryPackages(packagesDir); + oldContexts = contexts; + contexts = []; + } + } + for (var entry in directory.listSync()) { + if (entry is Directory) { + if (packages == null || !entry.path.endsWith("/packages")) { + findRoots(entry); + } + } + } + if (packages != null) { + oldContexts.add(_PackageContext(directory, packages, contexts)); + contexts = oldContexts; + } + } + + findRoots(directory); + // If the root is not itself context root, add a the wrapper context. + if (contexts.length == 1 && contexts[0].directory == directory) { + return contexts[0]; + } + return _PackageContext(directory, root, contexts); + } +} + +class _PackageContext implements PackageContext { + final Directory directory; + final Packages packages; + final List children; + _PackageContext(this.directory, this.packages, List children) + : children = List.unmodifiable(children); + + Map asMap() { + var result = HashMap(); + void recurse(_PackageContext current) { + result[current.directory] = current.packages; + for (var child in current.children) { + recurse(child); + } + } + + recurse(this); + return result; + } + + PackageContext operator [](Directory directory) { + var path = directory.path; + if (!path.startsWith(this.directory.path)) { + throw ArgumentError("Not inside $path: $directory"); + } + var current = this; + // The current path is know to agree with directory until deltaIndex. + var deltaIndex = current.directory.path.length; + List children = current.children; + var i = 0; + while (i < children.length) { + // TODO(lrn): Sort children and use binary search. + _PackageContext child = children[i]; + var childPath = child.directory.path; + if (_stringsAgree(path, childPath, deltaIndex, childPath.length)) { + deltaIndex = childPath.length; + if (deltaIndex == path.length) { + return child; + } + current = child; + children = current.children; + i = 0; + continue; + } + i++; + } + return current; + } + + static bool _stringsAgree(String a, String b, int start, int end) { + if (a.length < end || b.length < end) return false; + for (var i = start; i < end; i++) { + if (a.codeUnitAt(i) != b.codeUnitAt(i)) return false; + } + return true; + } +} + +Packages _loadPackagesFile(File file) { + var uri = Uri.file(file.path); + var bytes = file.readAsBytesSync(); + var map = pkgfile.parse(bytes, uri); + return MapPackages(map); +} diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 98b31f1f9..bca865d70 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -4,7 +4,7 @@ /// A package configuration is a way to assign file paths to package URIs, /// and vice-versa, -library package_config.package_config; +library package_config.package_config_discovery; import "dart:io" show File, Directory; import "dart:typed_data" show Uint8List; @@ -12,11 +12,9 @@ import "dart:typed_data" show Uint8List; import "src/discovery.dart" as discover; import "src/errors.dart" show throwError; import "src/package_config.dart"; -import "src/package_config_json.dart"; +import "src/package_config_io.dart"; -export "src/package_config.dart" - show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; -export "src/errors.dart" show PackageConfigError; +export "package_config_types.dart"; /// Reads a specific package configuration file. /// @@ -173,4 +171,4 @@ Future findPackageConfigUri(Uri location, /// `"generator"` entry. Future savePackageConfig( PackageConfig configuration, Directory directory) => - writePackageConfigJson(configuration, directory); + writePackageConfigJsonFile(configuration, directory); diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart new file mode 100644 index 000000000..f0637b11b --- /dev/null +++ b/pkgs/package_config/lib/package_config_types.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2019, 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. + +/// A package configuration is a way to assign file paths to package URIs, +/// and vice-versa, +library package_config.package_config; + +export "src/package_config.dart" + show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; +export "src/errors.dart" show PackageConfigError; diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart new file mode 100644 index 000000000..203f32fdb --- /dev/null +++ b/pkgs/package_config/lib/packages.dart @@ -0,0 +1,96 @@ +// Copyright (c) 2015, 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. + +@Deprecated("Use the package_config.json based API") +library package_config.packages; + +import "src/packages_impl.dart"; + +/// A package resolution strategy. +/// +/// Allows converting a `package:` URI to a different kind of URI. +/// +/// May also allow listing the available packages and converting +/// to a `Map` that gives the base location of each available +/// package. In some cases there is no way to find the available packages, +/// in which case [packages] and [asMap] will throw if used. +/// One such case is if the packages are resolved relative to a +/// `packages/` directory available over HTTP. +@Deprecated("Use the package_config.json based API") +abstract class Packages { + /// A [Packages] resolver containing no packages. + /// + /// This constant object is returned by [find] above if no + /// package resolution strategy is found. + static const Packages noPackages = NoPackages(); + + /// Resolve a package URI into a non-package URI. + /// + /// Translates a `package:` URI, according to the package resolution + /// strategy, into a URI that can be loaded. + /// By default, only `file`, `http` and `https` URIs are returned. + /// Custom `Packages` objects may return other URIs. + /// + /// If resolution fails because a package with the requested package name + /// is not available, the [notFound] function is called. + /// If no `notFound` function is provided, it defaults to throwing an error. + /// + /// The [packageUri] must be a valid package URI. + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}); + + /// Return the names of the available packages. + /// + /// Returns an iterable that allows iterating the names of available packages. + /// + /// Some `Packages` objects are unable to find the package names, + /// and getting `packages` from such a `Packages` object will throw. + Iterable get packages; + + /// Retrieve metadata associated with a package. + /// + /// Metadata have string keys and values, and are looked up by key. + /// + /// Returns `null` if the argument is not a valid package name, + /// or if the package is not one of the packages configured by + /// this packages object, or if the package does not have associated + /// metadata with the provided [key]. + /// + /// Not all `Packages` objects can support metadata. + /// Those will always return `null`. + String packageMetadata(String packageName, String key); + + /// Retrieve metadata associated with a library. + /// + /// If [libraryUri] is a `package:` URI, the returned value + /// is the same that would be returned by [packageMetadata] with + /// the package's name and the same key. + /// + /// If [libraryUri] is not a `package:` URI, and this [Packages] + /// object has a [defaultPackageName], then the [key] is looked + /// up on the default package instead. + /// + /// Otherwise the result is `null`. + String libraryMetadata(Uri libraryUri, String key); + + /// Return the names-to-base-URI mapping of the available packages. + /// + /// Returns a map from package name to a base URI. + /// The [resolve] method will resolve a package URI with a specific package + /// name to a path extending the base URI that this map gives for that + /// package name. + /// + /// Some `Packages` objects are unable to find the package names, + /// and calling `asMap` on such a `Packages` object will throw. + Map asMap(); + + /// The name of the "default package". + /// + /// A default package is a package that *non-package* libraries + /// may be considered part of for some purposes. + /// + /// The value is `null` if there is no default package. + /// Not all implementations of [Packages] supports a default package, + /// and will always have a `null` value for those. + String get defaultPackageName; +} diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart new file mode 100644 index 000000000..ef0b0b3ca --- /dev/null +++ b/pkgs/package_config/lib/packages_file.dart @@ -0,0 +1,232 @@ +// Copyright (c) 2015, 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. + +@Deprecated("Use the package_config.json based API") +library package_config.packages_file; + +import "package:charcode/ascii.dart"; + +import "src/util.dart" show isValidPackageName; + +/// Parses a `.packages` file into a map from package name to base URI. +/// +/// The [source] is the byte content of a `.packages` file, assumed to be +/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII, +/// so Latin-1 or Windows-1252 encoding will also work fine. +/// +/// If the file content is available as a string, its [String.codeUnits] can +/// be used as the `source` argument of this function. +/// +/// The [baseLocation] is used as a base URI to resolve all relative +/// URI references against. +/// If the content was read from a file, `baseLocation` should be the +/// location of that file. +/// +/// If [allowDefaultPackage] is set to true, an entry with an empty package name +/// is accepted. This entry does not correspond to a package, but instead +/// represents a *default package* which non-package libraries may be considered +/// part of in some cases. The value of that entry must be a valid package name. +/// +/// Returns a simple mapping from package name to package location. +/// If default package is allowed, the map maps the empty string to the default package's name. +Map parse(List source, Uri baseLocation, + {bool allowDefaultPackage = false}) { + var index = 0; + var result = {}; + while (index < source.length) { + var isComment = false; + var start = index; + var separatorIndex = -1; + var end = source.length; + var char = source[index++]; + if (char == $cr || char == $lf) { + continue; + } + if (char == $colon) { + if (!allowDefaultPackage) { + throw FormatException("Missing package name", source, index - 1); + } + separatorIndex = index - 1; + } + isComment = char == $hash; + while (index < source.length) { + char = source[index++]; + if (char == $colon && separatorIndex < 0) { + separatorIndex = index - 1; + } else if (char == $cr || char == $lf) { + end = index - 1; + break; + } + } + if (isComment) continue; + if (separatorIndex < 0) { + throw FormatException("No ':' on line", source, index - 1); + } + var packageName = String.fromCharCodes(source, start, separatorIndex); + if (packageName.isEmpty + ? !allowDefaultPackage + : !isValidPackageName(packageName)) { + throw FormatException("Not a valid package name", packageName, 0); + } + var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); + Uri packageLocation; + if (packageName.isEmpty) { + if (!isValidPackageName(packageValue)) { + throw FormatException( + "Default package entry value is not a valid package name"); + } + packageLocation = Uri(path: packageValue); + } else { + packageLocation = baseLocation.resolve(packageValue); + if (!packageLocation.path.endsWith('/')) { + packageLocation = + packageLocation.replace(path: packageLocation.path + "/"); + } + } + if (result.containsKey(packageName)) { + if (packageName.isEmpty) { + throw FormatException( + "More than one default package entry", source, start); + } + throw FormatException("Same package name occured twice", source, start); + } + result[packageName] = packageLocation; + } + return result; +} + +/// Writes the mapping to a [StringSink]. +/// +/// If [comment] is provided, the output will contain this comment +/// with `# ` in front of each line. +/// Lines are defined as ending in line feed (`'\n'`). If the final +/// line of the comment doesn't end in a line feed, one will be added. +/// +/// If [baseUri] is provided, package locations will be made relative +/// to the base URI, if possible, before writing. +/// +/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an +/// empty string mapping to the _default package name_. +/// +/// All the keys of [packageMapping] must be valid package names, +/// and the values must be URIs that do not have the `package:` scheme. +void write(StringSink output, Map packageMapping, + {Uri baseUri, String comment, bool allowDefaultPackage = false}) { + ArgumentError.checkNotNull(allowDefaultPackage, 'allowDefaultPackage'); + + if (baseUri != null && !baseUri.isAbsolute) { + throw ArgumentError.value(baseUri, "baseUri", "Must be absolute"); + } + + if (comment != null) { + var lines = comment.split('\n'); + if (lines.last.isEmpty) lines.removeLast(); + for (var commentLine in lines) { + output.write('# '); + output.writeln(commentLine); + } + } else { + output.write("# generated by package:package_config at "); + output.write(DateTime.now()); + output.writeln(); + } + + packageMapping.forEach((String packageName, Uri uri) { + // If [packageName] is empty then [uri] is the _default package name_. + if (allowDefaultPackage && packageName.isEmpty) { + final defaultPackageName = uri.toString(); + if (!isValidPackageName(defaultPackageName)) { + throw ArgumentError.value( + defaultPackageName, + 'defaultPackageName', + '"$defaultPackageName" is not a valid package name', + ); + } + output.write(':'); + output.write(defaultPackageName); + output.writeln(); + return; + } + // Validate packageName. + if (!isValidPackageName(packageName)) { + throw ArgumentError('"$packageName" is not a valid package name'); + } + if (uri.scheme == "package") { + throw ArgumentError.value( + "Package location must not be a package: URI", uri.toString()); + } + output.write(packageName); + output.write(':'); + // If baseUri provided, make uri relative. + if (baseUri != null) { + uri = _relativize(uri, baseUri); + } + if (!uri.path.endsWith('/')) { + uri = uri.replace(path: uri.path + '/'); + } + output.write(uri); + output.writeln(); + }); +} + +/// Attempts to return a relative URI for [uri]. +/// +/// The result URI satisfies `baseUri.resolveUri(result) == uri`, +/// but may be relative. +/// The `baseUri` must be absolute. +Uri _relativize(Uri uri, Uri baseUri) { + assert(baseUri.isAbsolute); + if (uri.hasQuery || uri.hasFragment) { + uri = Uri( + scheme: uri.scheme, + userInfo: uri.hasAuthority ? uri.userInfo : null, + host: uri.hasAuthority ? uri.host : null, + port: uri.hasAuthority ? uri.port : null, + path: uri.path); + } + + // Already relative. We assume the caller knows what they are doing. + if (!uri.isAbsolute) return uri; + + if (baseUri.scheme != uri.scheme) { + return uri; + } + + // If authority differs, we could remove the scheme, but it's not worth it. + if (uri.hasAuthority != baseUri.hasAuthority) return uri; + if (uri.hasAuthority) { + if (uri.userInfo != baseUri.userInfo || + uri.host.toLowerCase() != baseUri.host.toLowerCase() || + uri.port != baseUri.port) { + return uri; + } + } + + baseUri = baseUri.normalizePath(); + var base = baseUri.pathSegments.toList(); + if (base.isNotEmpty) { + base = List.from(base)..removeLast(); + } + uri = uri.normalizePath(); + var target = uri.pathSegments.toList(); + if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); + var index = 0; + while (index < base.length && index < target.length) { + if (base[index] != target[index]) { + break; + } + index++; + } + if (index == base.length) { + if (index == target.length) { + return Uri(path: "./"); + } + return Uri(path: target.skip(index).join('/')); + } else if (index > 0) { + return Uri( + path: '../' * (base.length - index) + target.skip(index).join('/')); + } else { + return uri; + } +} diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 14033ed35..5d3172f26 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -5,6 +5,8 @@ import "dart:io"; import 'dart:typed_data'; +import 'package_config_io.dart'; + import "errors.dart"; import "package_config_impl.dart"; import "package_config_json.dart"; diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 08c4a9691..364df75b1 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -2,8 +2,11 @@ // 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. +import 'dart:typed_data'; + import 'errors.dart'; import "package_config_impl.dart"; +import 'package_config_json.dart'; /// A package configuration. /// @@ -21,14 +24,27 @@ abstract class PackageConfig { /// A package configuration with no available packages. /// Is used as a default value where a package configuration /// is expected, but none have been specified or found. - static const PackageConfig empty = const SimplePackageConfig.empty(); + static const PackageConfig empty = SimplePackageConfig.empty(); /// Creats a package configuration with the provided available [packages]. /// /// The packages must be valid packages (valid package name, valid /// absolute directory URIs, valid language version, if any), - /// and there must not be two packages with the same name or with - /// overlapping root directories. + /// and there must not be two packages with the same name. + /// + /// The package's root ([Package.rootUri]) and package-root + /// ([Package.packageUriRoot]) paths must satisfy a number of constraints + /// We say that one path (which we know ends with a `/` charater) + /// is inside another path, if the latter path is a prefix of the former path, + /// including the two paths being the same. + /// + /// * No package's root must be the same as another package's root. + /// * The package-root of a package must be inside the pacakge's root. + /// * If one package's package-root is inside another package's root, + /// then the latter package's package root must not be inside the former + /// package's root. (No getting between a package and its package root!) + /// This also disallows a package's root being the same as another + /// package's package root. /// /// If supplied, the [extraData] will be available as the /// [PackageConfig.extraData] of the created configuration. @@ -37,6 +53,93 @@ abstract class PackageConfig { factory PackageConfig(Iterable packages, {dynamic extraData}) => SimplePackageConfig(maxVersion, packages, extraData); + /// Parses a package configuration file. + /// + /// The [bytes] must be an UTF-8 encoded JSON object + /// containing a valid package configuration. + /// + /// The [baseUri] is used as the base for resolving relative + /// URI references in the configuration file. If the configuration + /// has been read from a file, the [baseUri] can be the URI of that + /// file, or of the directory it occurs in. + /// + /// If [onError] is provided, errors found during parsing or building + /// the configuration are reported by calling [onError] instead of + /// throwing, and parser makes a *best effort* attempt to continue + /// despite the error. The input must still be valid JSON. + /// The result may be a [PackageConfig.empty] if there is no way to + /// extract useful information from the bytes. + static PackageConfig parseBytes(Uint8List bytes, Uri baseUri, + {void onError(Object error)}) => + parsePackageConfigBytes(bytes, baseUri, onError ?? throwError); + + /// Parses a package configuration file. + /// + /// The [configuration] must be a JSON object + /// containing a valid package configuration. + /// + /// The [baseUri] is used as the base for resolving relative + /// URI references in the configuration file. If the configuration + /// has been read from a file, the [baseUri] can be the URI of that + /// file, or of the directory it occurs in. + /// + /// If [onError] is provided, errors found during parsing or building + /// the configuration are reported by calling [onError] instead of + /// throwing, and parser makes a *best effort* attempt to continue + /// despite the error. The input must still be valid JSON. + /// The result may be a [PackageConfig.empty] if there is no way to + /// extract useful information from the bytes. + static PackageConfig parseString(String configuration, Uri baseUri, + {void onError(Object error)}) => + parsePackageConfigString(configuration, baseUri, onError ?? throwError); + + /// Parses the JSON data of a package configuration file. + /// + /// The [configuration] must be a JSON-like Dart data structure, + /// like the one provided by parsing JSON text using `dart:convert`, + /// containing a valid package configuration. + /// + /// The [baseUri] is used as the base for resolving relative + /// URI references in the configuration file. If the configuration + /// has been read from a file, the [baseUri] can be the URI of that + /// file, or of the directory it occurs in. + /// + /// If [onError] is provided, errors found during parsing or building + /// the configuration are reported by calling [onError] instead of + /// throwing, and parser makes a *best effort* attempt to continue + /// despite the error. The input must still be valid JSON. + /// The result may be a [PackageConfig.empty] if there is no way to + /// extract useful information from the bytes. + static PackageConfig parseJson(dynamic jsonData, Uri baseUri, + {void onError(Object error)}) => + parsePackageConfigJson(jsonData, baseUri, onError ?? throwError); + + /// Writes a configuration file for this configuration on [output]. + /// + /// If [baseUri] is provided, URI references in the generated file + /// will be made relative to [baseUri] where possible. + static void writeBytes(PackageConfig configuration, Sink output, + [Uri /*?*/ baseUri]) { + writePackageConfigJsonUtf8(configuration, baseUri, output); + } + + /// Writes a configuration JSON text for this configuration on [output]. + /// + /// If [baseUri] is provided, URI references in the generated file + /// will be made relative to [baseUri] where possible. + static void writeString(PackageConfig configuration, StringSink output, + [Uri /*?*/ baseUri]) { + writePackageConfigJsonString(configuration, baseUri, output); + } + + /// Converts a configuration to a JSON-like data structure. + /// + /// If [baseUri] is provided, URI references in the generated data + /// will be made relative to [baseUri] where possible. + static Map toJson(PackageConfig configuration, + [Uri /*?*/ baseUri]) => + packageConfigToJson(configuration, baseUri); + /// The configuration version number. /// /// Currently this is 1 or 2, where diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 39633fe4b..f68a9ea75 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -8,6 +8,8 @@ import "util.dart"; export "package_config.dart"; +// Implementations of the main data types exposed by the API of this package. + class SimplePackageConfig implements PackageConfig { final int version; final Map _packages; @@ -90,7 +92,7 @@ class SimplePackageConfig implements PackageConfig { onError(PackageConfigArgumentError( originalPackages, "packages", - "Packages ${package.name} and ${existingPackage.name}" + "Packages ${package.name} and ${existingPackage.name} " "have the same root directory: ${package.root}.\n")); } else { assert(error.isPackageRootConflict); @@ -126,7 +128,7 @@ class SimplePackageConfig implements PackageConfig { Package /*?*/ packageOf(Uri file) => _packageTree.packageOf(file); Uri /*?*/ resolve(Uri packageUri) { - String packageName = checkValidPackageUri(packageUri, "packageUri"); + var packageName = checkValidPackageUri(packageUri, "packageUri"); return _packages[packageName]?.packageUriRoot?.resolveUri( Uri(path: packageUri.path.substring(packageName.length + 1))); } @@ -187,7 +189,7 @@ class SimplePackage implements Package { LanguageVersion /*?*/ languageVersion, dynamic extraData, void onError(Object error)) { - bool fatalError = false; + var fatalError = false; var invalidIndex = checkPackageName(name); if (invalidIndex >= 0) { onError(PackageConfigFormatException( @@ -305,7 +307,7 @@ LanguageVersion parseLanguageVersion( abstract class _SimpleLanguageVersionBase implements LanguageVersion { int compareTo(LanguageVersion other) { - int result = major.compareTo(other.major); + var result = major.compareTo(other.major); if (result != 0) return result; return minor.compareTo(other.minor); } @@ -342,16 +344,32 @@ abstract class PackageTree { /// Packages of a package configuration ordered by root path. /// +/// A package has a root path and a package root path, where the latter +/// contains the files exposed by `package:` URIs. +/// /// A package is said to be inside another package if the root path URI of /// the latter is a prefix of the root path URI of the former. +/// /// No two packages of a package may have the same root path, so this /// path prefix ordering defines a tree-like partial ordering on packages /// of a configuration. /// +/// The package root path of a package must not be inside another package's +/// root path. +/// Entire other packages are allowed inside a package's root or +/// package root path. +/// /// The package tree contains an ordered mapping of unrelated packages /// (represented by their name) to their immediately nested packages' names. class MutablePackageTree implements PackageTree { + /// A list of packages that are not nested inside each other. final List packages = []; + + /// The tree of the immediately nested packages inside each package. + /// + /// Indexed by [Package.name]. + /// If a package has no nested packages (which is most often the case), + /// there is no tree object associated with it. Map /*?*/ _packageChildren; Iterable get allPackages sync* { @@ -365,30 +383,38 @@ class MutablePackageTree implements PackageTree { /// /// Reports a [ConflictException] if the added package conflicts with an /// existing package. - /// It conflicts if it has the same root path, or if the new package - /// contains the existing package's package root. + /// It conflicts if its root or package root is the same as another + /// package's root or package root, or is between the two. /// /// If a conflict is detected between [package] and a previous package, /// then [onError] is called with a [ConflictException] object /// and the [package] is not added to the tree. + /// + /// The packages are added in order of their root path. + /// It is never necessary to insert a node between two existing levels. void add(int start, SimplePackage package, void onError(Object error)) { var path = package.root.toString(); - for (var childPackage in packages) { - var childPath = childPackage.root.toString(); - assert(childPath.length > start); - assert(path.startsWith(childPath.substring(0, start))); - if (_beginsWith(start, childPath, path)) { - var childPathLength = childPath.length; - if (path.length == childPathLength) { - onError(ConflictException.root(package, childPackage)); + for (var treePackage in packages) { + // Check is package is inside treePackage. + var treePackagePath = treePackage.root.toString(); + assert(treePackagePath.length > start); + assert(path.startsWith(treePackagePath.substring(0, start))); + if (_beginsWith(start, treePackagePath, path)) { + // Package *is* inside treePackage. + var treePackagePathLength = treePackagePath.length; + if (path.length == treePackagePathLength) { + // Has same root. Do not add package. + onError(ConflictException.root(package, treePackage)); return; } - var childPackageRoot = childPackage.packageUriRoot.toString(); - if (_beginsWith(childPathLength, childPackageRoot, path)) { - onError(ConflictException.packageRoot(package, childPackage)); + var treePackageUriRoot = treePackage.packageUriRoot.toString(); + if (_beginsWith(treePackagePathLength, path, treePackageUriRoot)) { + // The treePackage's package root is inside package, which is inside + // the treePackage. This is not allowed. + onError(ConflictException.packageRoot(package, treePackage)); return; } - _treeOf(childPackage).add(childPathLength, package, onError); + _treeOf(treePackage).add(treePackagePathLength, package, onError); return; } } @@ -454,7 +480,7 @@ class EmptyPackageTree implements PackageTree { /// already have been matched. bool _beginsWith(int start, String parentPath, String longerPath) { if (longerPath.length < parentPath.length) return false; - for (int i = start; i < parentPath.length; i++) { + for (var i = start; i < parentPath.length; i++) { if (longerPath.codeUnitAt(i) != parentPath.codeUnitAt(i)) return false; } return true; diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart new file mode 100644 index 000000000..d59972f9a --- /dev/null +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -0,0 +1,155 @@ +// Copyright (c) 2019, 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. + +// dart:io dependent functionality for reading and writing configuration files. + +import "dart:convert"; +import "dart:io"; +import "dart:typed_data"; + +import "discovery.dart" show packageConfigJsonPath; +import "errors.dart"; +import "package_config_impl.dart"; +import "package_config_json.dart"; +import "packages_file.dart" as packages_file; +import "util.dart"; + +/// Reads a package configuration file. +/// +/// Detects whether the [file] is a version one `.packages` file or +/// a version two `package_config.json` file. +/// +/// If the [file] is a `.packages` file and [preferNewest] is true, +/// first checks whether there is an adjacent `.dart_tool/package_config.json` +/// file, and if so, reads that instead. +/// If [preferNewset] is false, the specified file is loaded even if it is +/// a `.packages` file and there is an available `package_config.json` file. +/// +/// The file must exist and be a normal file. +Future readAnyConfigFile( + File file, bool preferNewest, void onError(Object error)) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + var firstChar = firstNonWhitespaceChar(bytes); + if (firstChar != $lbrace) { + // Definitely not a JSON object, probably a .packages. + if (preferNewest) { + var alternateFile = File( + pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); + if (alternateFile.existsSync()) { + Uint8List /*?*/ bytes; + try { + bytes = await alternateFile.readAsBytes(); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + if (bytes != null) { + return parsePackageConfigBytes(bytes, alternateFile.uri, onError); + } + } + } + return packages_file.parse(bytes, file.uri, onError); + } + return parsePackageConfigBytes(bytes, file.uri, onError); +} + +/// Like [readAnyConfigFile] but uses a URI and an optional loader. +Future readAnyConfigFileUri( + Uri file, + Future loader(Uri uri) /*?*/, + void onError(Object error), + bool preferNewest) async { + if (file.isScheme("package")) { + throw PackageConfigArgumentError( + file, "file", "Must not be a package: URI"); + } + if (loader == null) { + if (file.isScheme("file")) { + return readAnyConfigFile(File.fromUri(file), preferNewest, onError); + } + loader = defaultLoader; + } + Uint8List bytes; + try { + bytes = await loader(file); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + if (bytes == null) { + onError(PackageConfigArgumentError( + file.toString(), "file", "File cannot be read")); + return const SimplePackageConfig.empty(); + } + var firstChar = firstNonWhitespaceChar(bytes); + if (firstChar != $lbrace) { + // Definitely not a JSON object, probably a .packages. + if (preferNewest) { + // Check if there is a package_config.json file. + var alternateFile = file.resolveUri(packageConfigJsonPath); + Uint8List alternateBytes; + try { + alternateBytes = await loader(alternateFile); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + if (alternateBytes != null) { + return parsePackageConfigBytes(alternateBytes, alternateFile, onError); + } + } + return packages_file.parse(bytes, file, onError); + } + return parsePackageConfigBytes(bytes, file, onError); +} + +Future readPackageConfigJsonFile( + File file, void onError(Object error)) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (error) { + onError(error); + return const SimplePackageConfig.empty(); + } + return parsePackageConfigBytes(bytes, file.uri, onError); +} + +Future readDotPackagesFile( + File file, void onError(Object error)) async { + Uint8List bytes; + try { + bytes = await file.readAsBytes(); + } catch (error) { + onError(error); + return const SimplePackageConfig.empty(); + } + return packages_file.parse(bytes, file.uri, onError); +} + +Future writePackageConfigJsonFile( + PackageConfig config, Directory targetDirectory) async { + // Write .dart_tool/package_config.json first. + var file = + File(pathJoin(targetDirectory.path, ".dart_tool", "package_config.json")); + var baseUri = file.uri; + var sink = file.openWrite(encoding: utf8); + writePackageConfigJsonUtf8(config, baseUri, sink); + var doneJson = sink.close(); + + // Write .packages too. + file = File(pathJoin(targetDirectory.path, ".packages")); + baseUri = file.uri; + sink = file.openWrite(encoding: utf8); + writeDotPackages(config, baseUri, sink); + var donePackages = sink.close(); + + await Future.wait([doneJson, donePackages]); +} diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index f56c91271..b9b34165b 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -2,11 +2,11 @@ // 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. +// Parsing and serialization of package configurations. + import "dart:convert"; -import "dart:io"; import "dart:typed_data"; -import "discovery.dart" show packageConfigJsonPath; import "errors.dart"; import "package_config_impl.dart"; import "packages_file.dart" as packages_file; @@ -30,125 +30,6 @@ const String _generatedKey = "generated"; const String _generatorKey = "generator"; const String _generatorVersionKey = "generatorVersion"; -/// Reads a package configuration file. -/// -/// Detects whether the [file] is a version one `.packages` file or -/// a version two `package_config.json` file. -/// -/// If the [file] is a `.packages` file and [preferNewest] is true, -/// first checks whether there is an adjacent `.dart_tool/package_config.json` -/// file, and if so, reads that instead. -/// If [preferNewset] is false, the specified file is loaded even if it is -/// a `.packages` file and there is an available `package_config.json` file. -/// -/// The file must exist and be a normal file. -Future readAnyConfigFile( - File file, bool preferNewest, void onError(Object error)) async { - Uint8List bytes; - try { - bytes = await file.readAsBytes(); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - int firstChar = firstNonWhitespaceChar(bytes); - if (firstChar != $lbrace) { - // Definitely not a JSON object, probably a .packages. - if (preferNewest) { - var alternateFile = File( - pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); - if (alternateFile.existsSync()) { - Uint8List /*?*/ bytes; - try { - bytes = await alternateFile.readAsBytes(); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - if (bytes != null) { - return parsePackageConfigBytes(bytes, alternateFile.uri, onError); - } - } - } - return packages_file.parse(bytes, file.uri, onError); - } - return parsePackageConfigBytes(bytes, file.uri, onError); -} - -/// Like [readAnyConfigFile] but uses a URI and an optional loader. -Future readAnyConfigFileUri( - Uri file, - Future loader(Uri uri) /*?*/, - void onError(Object error), - bool preferNewest) async { - if (file.isScheme("package")) { - throw PackageConfigArgumentError( - file, "file", "Must not be a package: URI"); - } - if (loader == null) { - if (file.isScheme("file")) { - return readAnyConfigFile(File.fromUri(file), preferNewest, onError); - } - loader = defaultLoader; - } - Uint8List bytes; - try { - bytes = await loader(file); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - if (bytes == null) { - onError(PackageConfigArgumentError( - file.toString(), "file", "File cannot be read")); - return const SimplePackageConfig.empty(); - } - int firstChar = firstNonWhitespaceChar(bytes); - if (firstChar != $lbrace) { - // Definitely not a JSON object, probably a .packages. - if (preferNewest) { - // Check if there is a package_config.json file. - var alternateFile = file.resolveUri(packageConfigJsonPath); - Uint8List alternateBytes; - try { - alternateBytes = await loader(alternateFile); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - if (alternateBytes != null) { - return parsePackageConfigBytes(alternateBytes, alternateFile, onError); - } - } - return packages_file.parse(bytes, file, onError); - } - return parsePackageConfigBytes(bytes, file, onError); -} - -Future readPackageConfigJsonFile( - File file, void onError(Object error)) async { - Uint8List bytes; - try { - bytes = await file.readAsBytes(); - } catch (error) { - onError(error); - return const SimplePackageConfig.empty(); - } - return parsePackageConfigBytes(bytes, file.uri, onError); -} - -Future readDotPackagesFile( - File file, void onError(Object error)) async { - Uint8List bytes; - try { - bytes = await file.readAsBytes(); - } catch (error) { - onError(error); - return const SimplePackageConfig.empty(); - } - return packages_file.parse(bytes, file.uri, onError); -} - final _jsonUtf8Decoder = json.fuse(utf8).decoder; PackageConfig parsePackageConfigBytes( @@ -164,6 +45,18 @@ PackageConfig parsePackageConfigBytes( return parsePackageConfigJson(jsonObject, file, onError); } +PackageConfig parsePackageConfigString( + String source, Uri file, void onError(Object error)) { + var jsonObject; + try { + jsonObject = jsonDecode(source); + } on FormatException catch (e) { + onError(PackageConfigFormatException(e.message, e.source, e.offset)); + return const SimplePackageConfig.empty(); + } + return parsePackageConfigJson(jsonObject, file, onError); +} + /// Creates a [PackageConfig] from a parsed JSON-like object structure. /// /// The [json] argument must be a JSON object (`Map`) @@ -221,9 +114,9 @@ PackageConfig parsePackageConfigJson( String /*?*/ packageUri; String /*?*/ languageVersion; Map /*?*/ extraData; - bool hasName = false; - bool hasRoot = false; - bool hasVersion = false; + var hasName = false; + var hasRoot = false; + var hasVersion = false; entry.forEach((key, value) { switch (key) { case _nameKey: @@ -253,9 +146,9 @@ PackageConfig parsePackageConfigJson( onError(PackageConfigFormatException("Missing rootUri entry", entry)); } if (name == null || rootUri == null) return null; - Uri root = baseLocation.resolve(rootUri); + var root = baseLocation.resolve(rootUri); if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/"); - Uri packageRoot = root; + var packageRoot = root; if (packageUri != null) packageRoot = root.resolve(packageUri); if (!packageRoot.path.endsWith("/")) { packageRoot = packageRoot.replace(path: packageRoot.path + "/"); @@ -281,7 +174,7 @@ PackageConfig parsePackageConfigJson( var map = checkType>(json, "value"); if (map == null) return const SimplePackageConfig.empty(); - Map /*?*/ extraData = null; + Map /*?*/ extraData; List /*?*/ packageList; int /*?*/ configVersion; map.forEach((key, value) { @@ -326,31 +219,45 @@ PackageConfig parsePackageConfigJson( }); } -Future writePackageConfigJson( - PackageConfig config, Directory targetDirectory) async { - // Write .dart_tool/package_config.json first. - var file = - File(pathJoin(targetDirectory.path, ".dart_tool", "package_config.json")); - var baseUri = file.uri; - var extraData = config.extraData; - var data = { - _configVersionKey: PackageConfig.maxVersion, - _packagesKey: [ - for (var package in config.packages) - { - _nameKey: package.name, - _rootUriKey: relativizeUri(package.root, baseUri), - if (package.root != package.packageUriRoot) - _packageUriKey: relativizeUri(package.packageUriRoot, package.root), - if (package.languageVersion != null && - package.languageVersion is! InvalidLanguageVersion) - _languageVersionKey: package.languageVersion.toString(), - ...?_extractExtraData(package.extraData, _packageNames), - } - ], - ...?_extractExtraData(config.extraData, _topNames), - }; +final _jsonUtf8Encoder = JsonUtf8Encoder(" "); + +void writePackageConfigJsonUtf8( + PackageConfig config, Uri baseUri, Sink> output) { + // Can be optimized. + var data = packageConfigToJson(config, baseUri); + output.add(_jsonUtf8Encoder.convert(data) as Uint8List); +} + +void writePackageConfigJsonString( + PackageConfig config, Uri baseUri, StringSink output) { + // Can be optimized. + var data = packageConfigToJson(config, baseUri); + output.write(JsonEncoder.withIndent(" ").convert(data) as Uint8List); +} +Map packageConfigToJson(PackageConfig config, Uri baseUri) => + { + ...?_extractExtraData(config.extraData, _topNames), + _configVersionKey: PackageConfig.maxVersion, + _packagesKey: [ + for (var package in config.packages) + { + _nameKey: package.name, + _rootUriKey: relativizeUri(package.root, baseUri).toString(), + if (package.root != package.packageUriRoot) + _packageUriKey: + relativizeUri(package.packageUriRoot, package.root) + .toString(), + if (package.languageVersion != null && + package.languageVersion is! InvalidLanguageVersion) + _languageVersionKey: package.languageVersion.toString(), + ...?_extractExtraData(package.extraData, _packageNames), + } + ], + }; + +void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) { + var extraData = config.extraData; // Write .packages too. String /*?*/ comment; if (extraData != null) { @@ -363,15 +270,8 @@ Future writePackageConfigJson( "${generated != null ? " on $generated" : ""}."; } } - file = File(pathJoin(targetDirectory.path, ".packages")); - baseUri = file.uri; - var buffer = StringBuffer(); - packages_file.write(buffer, config, baseUri: baseUri, comment: comment); - - await Future.wait([ - file.writeAsString(JsonEncoder.withIndent(" ").convert(data)), - file.writeAsString(buffer.toString()), - ]); + packages_file.write(output, config, baseUri: baseUri, comment: comment); + return; } /// If "extraData" is a JSON map, then return it, otherwise return null. diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 475a782a2..e65e7e8a6 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -31,15 +31,15 @@ PackageConfig parse( baseLocation, "baseLocation", "Must not be a package: URI")); return PackageConfig.empty; } - int index = 0; - List packages = []; - Set packageNames = {}; + var index = 0; + var packages = []; + var packageNames = {}; while (index < source.length) { - bool ignoreLine = false; - int start = index; - int separatorIndex = -1; - int end = source.length; - int char = source[index++]; + var ignoreLine = false; + var start = index; + var separatorIndex = -1; + var end = source.length; + var char = source[index++]; if (char == $cr || char == $lf) { continue; } @@ -50,8 +50,8 @@ PackageConfig parse( } else { ignoreLine = char == $hash; // Ignore if comment. } - int queryStart = -1; - int fragmentStart = -1; + var queryStart = -1; + var fragmentStart = -1; while (index < source.length) { char = source[index++]; if (char == $colon && separatorIndex < 0) { @@ -72,7 +72,7 @@ PackageConfig parse( continue; } var packageName = String.fromCharCodes(source, start, separatorIndex); - int invalidIndex = checkPackageName(packageName); + var invalidIndex = checkPackageName(packageName); if (invalidIndex >= 0) { onError(PackageConfigFormatException( "Not a valid package name", source, start + invalidIndex)); diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart new file mode 100644 index 000000000..19f103922 --- /dev/null +++ b/pkgs/package_config/lib/src/packages_impl.dart @@ -0,0 +1,128 @@ +// Copyright (c) 2015, 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. + +/// Implementations of [Packages] that may be used in either server or browser +/// based applications. For implementations that can only run in the browser, +/// see [package_config.packages_io_impl]. +@Deprecated("Use the package_config.json based API") +library package_config.packages_impl; + +import "dart:collection" show UnmodifiableMapView; + +import "../packages.dart"; +import "util.dart" show checkValidPackageUri; + +/// A [Packages] null-object. +class NoPackages implements Packages { + const NoPackages(); + + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { + var packageName = checkValidPackageUri(packageUri, "packageUri"); + if (notFound != null) return notFound(packageUri); + throw ArgumentError.value( + packageUri, "packageUri", 'No package named "$packageName"'); + } + + Iterable get packages => Iterable.empty(); + + Map asMap() => const {}; + + String get defaultPackageName => null; + + String packageMetadata(String packageName, String key) => null; + + String libraryMetadata(Uri libraryUri, String key) => null; +} + +/// Base class for [Packages] implementations. +/// +/// This class implements the [resolve] method in terms of a private +/// member +abstract class PackagesBase implements Packages { + Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { + packageUri = packageUri.normalizePath(); + var packageName = checkValidPackageUri(packageUri, "packageUri"); + var packageBase = getBase(packageName); + if (packageBase == null) { + if (notFound != null) return notFound(packageUri); + throw ArgumentError.value( + packageUri, "packageUri", 'No package named "$packageName"'); + } + var packagePath = packageUri.path.substring(packageName.length + 1); + return packageBase.resolve(packagePath); + } + + /// Find a base location for a package name. + /// + /// Returns `null` if no package exists with that name, and that can be + /// determined. + Uri getBase(String packageName); + + String get defaultPackageName => null; + + String packageMetadata(String packageName, String key) => null; + + String libraryMetadata(Uri libraryUri, String key) => null; +} + +/// A [Packages] implementation based on an existing map. +class MapPackages extends PackagesBase { + final Map _mapping; + MapPackages(this._mapping); + + Uri getBase(String packageName) => + packageName.isEmpty ? null : _mapping[packageName]; + + Iterable get packages => _mapping.keys; + + Map asMap() => UnmodifiableMapView(_mapping); + + String get defaultPackageName => _mapping[""]?.toString(); + + String packageMetadata(String packageName, String key) { + if (packageName.isEmpty) return null; + var uri = _mapping[packageName]; + if (uri == null || !uri.hasFragment) return null; + // This can be optimized, either by caching the map or by + // parsing incrementally instead of parsing the entire fragment. + return Uri.splitQueryString(uri.fragment)[key]; + } + + String libraryMetadata(Uri libraryUri, String key) { + if (libraryUri.isScheme("package")) { + return packageMetadata(libraryUri.pathSegments.first, key); + } + var defaultPackageNameUri = _mapping[""]; + if (defaultPackageNameUri != null) { + return packageMetadata(defaultPackageNameUri.toString(), key); + } + return null; + } +} + +/// A [Packages] implementation based on a remote (e.g., HTTP) directory. +/// +/// There is no way to detect which packages exist short of trying to use +/// them. You can't necessarily check whether a directory exists, +/// except by checking for a know file in the directory. +class NonFilePackagesDirectoryPackages extends PackagesBase { + final Uri _packageBase; + NonFilePackagesDirectoryPackages(this._packageBase); + + Uri getBase(String packageName) => _packageBase.resolve("$packageName/"); + + Error _failListingPackages() { + return UnsupportedError( + "Cannot list packages for a ${_packageBase.scheme}: " + "based package root"); + } + + Iterable get packages { + throw _failListingPackages(); + } + + Map asMap() { + throw _failListingPackages(); + } +} diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart new file mode 100644 index 000000000..b2277e7e0 --- /dev/null +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2015, 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. + +/// Implementations of [Packages] that can only be used in server based +/// applications. +@Deprecated("Use the package_config.json based API") +library package_config.packages_io_impl; + +import "dart:collection" show UnmodifiableMapView; +import "dart:io" show Directory; + +import "packages_impl.dart"; + +import "util.dart"; + +/// A [Packages] implementation based on a local directory. +class FilePackagesDirectoryPackages extends PackagesBase { + final Directory _packageDir; + final Map _packageToBaseUriMap = {}; + + FilePackagesDirectoryPackages(this._packageDir); + + Uri getBase(String packageName) { + return _packageToBaseUriMap.putIfAbsent(packageName, () { + return Uri.file(pathJoin(_packageDir.path, packageName, '.')); + }); + } + + Iterable _listPackageNames() { + return _packageDir + .listSync() + .whereType() + .map((e) => fileName(e.path)); + } + + Iterable get packages => _listPackageNames(); + + Map asMap() { + var result = {}; + for (var packageName in _listPackageNames()) { + result[packageName] = getBase(packageName); + } + return UnmodifiableMapView(result); + } +} diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index f39027d00..548f61d98 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -31,8 +31,8 @@ bool isValidPackageName(String string) { /// or `string.length` if the string contains no non-'.' character. int checkPackageName(String string) { // Becomes non-zero if any non-'.' character is encountered. - int nonDot = 0; - for (int i = 0; i < string.length; i++) { + var nonDot = 0; + for (var i = 0; i < string.length; i++) { var c = string.codeUnitAt(i); if (c > 0x7f || _validPackageNameCharacters.codeUnitAt(c) <= $space) { return i; @@ -74,13 +74,13 @@ String checkValidPackageUri(Uri packageUri, String name) { throw PackageConfigArgumentError( packageUri, name, "Package URIs must not start with a '/'"); } - int firstSlash = packageUri.path.indexOf('/'); + var firstSlash = packageUri.path.indexOf('/'); if (firstSlash == -1) { throw PackageConfigArgumentError(packageUri, name, "Package URIs must start with the package name followed by a '/'"); } - String packageName = packageUri.path.substring(0, firstSlash); - int badIndex = checkPackageName(packageName); + var packageName = packageUri.path.substring(0, firstSlash); + var badIndex = checkPackageName(packageName); if (badIndex >= 0) { if (packageName.isEmpty) { throw PackageConfigArgumentError( @@ -91,7 +91,7 @@ String checkValidPackageUri(Uri packageUri, String name) { "Package names must contain at least one non-'.' character"); } assert(badIndex < packageName.length); - int badCharCode = packageName.codeUnitAt(badIndex); + var badCharCode = packageName.codeUnitAt(badIndex); var badChar = "U+" + badCharCode.toRadixString(16).padLeft(4, '0'); if (badCharCode >= 0x20 && badCharCode <= 0x7e) { // Printable character. @@ -131,7 +131,7 @@ bool isUriPrefix(Uri prefix, Uri path) { /// /// Used to heuristically detect whether a file is a JSON file or an .ini file. int firstNonWhitespaceChar(List bytes) { - for (int i = 0; i < bytes.length; i++) { + for (var i = 0; i < bytes.length; i++) { var char = bytes[i]; if (char != 0x20 && char != 0x09 && char != 0x0a && char != 0x0d) { return char; @@ -156,7 +156,8 @@ int firstNonWhitespaceChar(List bytes) { /// `baseUri.resolveUri(result) == uri`, /// /// The `baseUri` must be absolute. -Uri relativizeUri(Uri uri, Uri baseUri) { +Uri relativizeUri(Uri uri, Uri /*?*/ baseUri) { + if (baseUri == null) return uri; assert(baseUri.isAbsolute); if (uri.hasQuery || uri.hasFragment) { uri = Uri( @@ -185,12 +186,12 @@ Uri relativizeUri(Uri uri, Uri baseUri) { } baseUri = baseUri.normalizePath(); - List base = [...baseUri.pathSegments]; + var base = [...baseUri.pathSegments]; if (base.isNotEmpty) base.removeLast(); uri = uri.normalizePath(); - List target = [...uri.pathSegments]; + var target = [...uri.pathSegments]; if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); - int index = 0; + var index = 0; while (index < base.length && index < target.length) { if (base[index] != target[index]) { break; @@ -204,7 +205,7 @@ Uri relativizeUri(Uri uri, Uri baseUri) { return Uri(path: target.skip(index).join('/')); } else if (index > 0) { var buffer = StringBuffer(); - for (int n = base.length - index; n > 0; --n) { + for (var n = base.length - index; n > 0; --n) { buffer.write("../"); } buffer.writeAll(target.skip(index), "/"); @@ -231,14 +232,14 @@ Future defaultLoader(Uri uri) async { Future _httpGet(Uri uri) async { assert(uri.isScheme("http") || uri.isScheme("https")); - HttpClient client = new HttpClient(); - HttpClientRequest request = await client.getUrl(uri); - HttpClientResponse response = await request.close(); + var client = HttpClient(); + var request = await client.getUrl(uri); + var response = await request.close(); if (response.statusCode != HttpStatus.ok) { return null; } - List> splitContent = await response.toList(); - int totalLength = 0; + var splitContent = await response.toList(); + var totalLength = 0; if (splitContent.length == 1) { var part = splitContent[0]; if (part is Uint8List) { @@ -248,8 +249,8 @@ Future _httpGet(Uri uri) async { for (var list in splitContent) { totalLength += list.length; } - Uint8List result = new Uint8List(totalLength); - int offset = 0; + var result = Uint8List(totalLength); + var offset = 0; for (Uint8List contentPart in splitContent) { result.setRange(offset, offset + contentPart.length, contentPart); offset += contentPart.length; @@ -264,7 +265,7 @@ Future _httpGet(Uri uri) async { /// path separator occurs in the string. String fileName(String path) { var separator = Platform.pathSeparator; - int lastSeparator = path.lastIndexOf(separator); + var lastSeparator = path.lastIndexOf(separator); if (lastSeparator < 0) return path; return path.substring(lastSeparator + separator.length); } @@ -276,7 +277,7 @@ String fileName(String path) { /// path separator occurs in the string. String dirName(String path) { var separator = Platform.pathSeparator; - int lastSeparator = path.lastIndexOf(separator); + var lastSeparator = path.lastIndexOf(separator); if (lastSeparator < 0) return ""; return path.substring(0, lastSeparator); } @@ -287,11 +288,11 @@ String dirName(String path) { /// inserted. String pathJoin(String part1, String part2, [String part3]) { var separator = Platform.pathSeparator; - String separator1 = part1.endsWith(separator) ? "" : separator; + var separator1 = part1.endsWith(separator) ? "" : separator; if (part3 == null) { return "$part1$separator1$part2"; } - String separator2 = part2.endsWith(separator) ? "" : separator; + var separator2 = part2.endsWith(separator) ? "" : separator; return "$part1$separator1$part2$separator2$part3"; } @@ -301,7 +302,7 @@ String pathJoin(String part1, String part2, [String part3]) { /// inserted. String pathJoinAll(Iterable parts) { var buffer = StringBuffer(); - String separator = ""; + var separator = ""; for (var part in parts) { buffer..write(separator)..write(part); separator = diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 7f47d2e2c..20a39c767 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 3.0.0-dev +version: 1.9.0-dev description: Support for working with Package Configuration files. author: Dart Team homepage: https://github.com/dart-lang/package_config @@ -8,4 +8,6 @@ environment: sdk: '>=2.7.0 <3.0.0' dev_dependencies: - test: ^1.3.0 + test: ^1.6.4 + matcher: ^0.12.5 + pedantic: 1.8.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 23efc6741..e4c93a592 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -50,7 +50,7 @@ void validatePackagesFile(PackageConfig resolver, Directory directory) { unorderedEquals(["foo", "bar", "baz"])); } -main() { +void main() { group("findPackages", () { // Finds package_config.json if there. fileTest("package_config.json", { @@ -61,7 +61,7 @@ main() { "package_config.json": packageConfigFile, } }, (Directory directory) async { - PackageConfig config = await findPackageConfig(directory); + var config = await findPackageConfig(directory); expect(config.version, 2); // Found package_config.json file. validatePackagesFile(config, directory); }); @@ -72,7 +72,7 @@ main() { "script.dart": "main(){}", "packages": {"shouldNotBeFound": {}} }, (Directory directory) async { - PackageConfig config = await findPackageConfig(directory); + var config = await findPackageConfig(directory); expect(config.version, 1); // Found .packages file. validatePackagesFile(config, directory); }); @@ -87,8 +87,7 @@ main() { "script.dart": "main(){}", } }, (Directory directory) async { - PackageConfig config = - await findPackageConfig(subdir(directory, "subdir/")); + var config = await findPackageConfig(subdir(directory, "subdir/")); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -98,7 +97,7 @@ main() { ".packages": packagesFile, "subdir": {"script.dart": "main(){}"} }, (Directory directory) async { - PackageConfig config; + var config; config = await findPackageConfig(subdir(directory, "subdir/")); expect(config.version, 1); validatePackagesFile(config, directory); @@ -110,7 +109,7 @@ main() { "foo": {}, } }, (Directory directory) async { - PackageConfig config = await findPackageConfig(directory); + var config = await findPackageConfig(directory); expect(config, null); }); @@ -152,7 +151,7 @@ main() { fileTest("invalid .packages", { ".packages": "not a .packages file", }, (Directory directory) async { - bool hadError = false; + var hadError = false; await findPackageConfig(directory, onError: expectAsync1((error) { hadError = true; @@ -164,7 +163,7 @@ main() { fileTest("invalid .packages as JSON", { ".packages": packageConfigFile, }, (Directory directory) async { - bool hadError = false; + var hadError = false; await findPackageConfig(directory, onError: expectAsync1((error) { hadError = true; @@ -178,7 +177,7 @@ main() { "package_config.json": "not a JSON file", } }, (Directory directory) async { - bool hadError = false; + var hadError = false; await findPackageConfig(directory, onError: expectAsync1((error) { hadError = true; @@ -192,7 +191,7 @@ main() { "package_config.json": packagesFile, } }, (Directory directory) async { - bool hadError = false; + var hadError = false; await findPackageConfig(directory, onError: expectAsync1((error) { hadError = true; @@ -213,23 +212,22 @@ main() { }, }; fileTest("directly", files, (Directory directory) async { - File file = + var file = dirFile(subdir(directory, ".dart_tool"), "package_config.json"); - PackageConfig config = await loadPackageConfig(file); + var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); fileTest("indirectly through .packages", files, (Directory directory) async { - File file = dirFile(directory, ".packages"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, ".packages"); + var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); fileTest("prefer .packages", files, (Directory directory) async { - File file = dirFile(directory, ".packages"); - PackageConfig config = - await loadPackageConfig(file, preferNewest: false); + var file = dirFile(directory, ".packages"); + var config = await loadPackageConfig(file, preferNewest: false); expect(config.version, 1); validatePackagesFile(config, directory); }); @@ -241,8 +239,8 @@ main() { "pheldagriff": packageConfigFile, }, }, (Directory directory) async { - File file = dirFile(directory, "subdir/pheldagriff"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, "subdir/pheldagriff"); + var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -252,8 +250,8 @@ main() { ".packages": packageConfigFile, }, }, (Directory directory) async { - File file = dirFile(directory, "subdir/.packages"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, "subdir/.packages"); + var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -261,8 +259,8 @@ main() { fileTest(".packages", { ".packages": packagesFile, }, (Directory directory) async { - File file = dirFile(directory, ".packages"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, ".packages"); + var config = await loadPackageConfig(file); expect(config.version, 1); validatePackagesFile(config, directory); }); @@ -270,21 +268,21 @@ main() { fileTest(".packages non-default name", { "pheldagriff": packagesFile, }, (Directory directory) async { - File file = dirFile(directory, "pheldagriff"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, "pheldagriff"); + var config = await loadPackageConfig(file); expect(config.version, 1); validatePackagesFile(config, directory); }); fileTest("no config found", {}, (Directory directory) { - File file = dirFile(directory, "anyname"); + var file = dirFile(directory, "anyname"); expect(() => loadPackageConfig(file), throwsA(TypeMatcher())); }); fileTest("no config found, handled", {}, (Directory directory) async { - File file = dirFile(directory, "anyname"); - bool hadError = false; + var file = dirFile(directory, "anyname"); + var hadError = false; await loadPackageConfig(file, onError: expectAsync1((error) { hadError = true; @@ -296,7 +294,7 @@ main() { fileTest("specified file syntax error", { "anyname": "syntax error", }, (Directory directory) { - File file = dirFile(directory, "anyname"); + var file = dirFile(directory, "anyname"); expect(() => loadPackageConfig(file), throwsFormatException); }); @@ -307,8 +305,8 @@ main() { "package_config.json": packageConfigFile, }, }, (Directory directory) async { - File file = dirFile(directory, "anyname"); - PackageConfig config = await loadPackageConfig(file); + var file = dirFile(directory, "anyname"); + var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -317,7 +315,7 @@ main() { fileTest("file syntax error with {", { ".packages": "{syntax error", }, (Directory directory) { - File file = dirFile(directory, ".packages"); + var file = dirFile(directory, ".packages"); expect(() => loadPackageConfig(file), throwsFormatException); }); }); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 081ec608f..109693c4c 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -4,8 +4,6 @@ library package_config.discovery_test; -import 'dart:io'; - import "package:test/test.dart"; import "package:package_config/package_config.dart"; @@ -51,7 +49,7 @@ void validatePackagesFile(PackageConfig resolver, Uri directory) { unorderedEquals(["foo", "bar", "baz"])); } -main() { +void main() { group("findPackages", () { // Finds package_config.json if there. loaderTest("package_config.json", { @@ -62,8 +60,7 @@ main() { "package_config.json": packageConfigFile, } }, (Uri directory, loader) async { - PackageConfig config = - await findPackageConfigUri(directory, loader: loader); + var config = await findPackageConfigUri(directory, loader: loader); expect(config.version, 2); // Found package_config.json file. validatePackagesFile(config, directory); }); @@ -74,8 +71,7 @@ main() { "script.dart": "main(){}", "packages": {"shouldNotBeFound": {}} }, (Uri directory, loader) async { - PackageConfig config = - await findPackageConfigUri(directory, loader: loader); + var config = await findPackageConfigUri(directory, loader: loader); expect(config.version, 1); // Found .packages file. validatePackagesFile(config, directory); }); @@ -90,8 +86,7 @@ main() { "script.dart": "main(){}", } }, (Uri directory, loader) async { - PackageConfig config = await findPackageConfigUri( - directory.resolve("subdir/"), + var config = await findPackageConfigUri(directory.resolve("subdir/"), loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); @@ -102,7 +97,7 @@ main() { ".packages": packagesFile, "subdir": {"script.dart": "main(){}"} }, (Uri directory, loader) async { - PackageConfig config; + var config; config = await findPackageConfigUri(directory.resolve("subdir/"), loader: loader); expect(config.version, 1); @@ -115,8 +110,7 @@ main() { "foo": {}, } }, (Uri directory, loader) async { - PackageConfig config = - await findPackageConfigUri(directory, loader: loader); + var config = await findPackageConfigUri(directory, loader: loader); expect(config, null); }); @@ -163,15 +157,15 @@ main() { }, }; loaderTest("directly", files, (Uri directory, loader) async { - Uri file = directory.resolve(".dart_tool/package_config.json"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve(".dart_tool/package_config.json"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); loaderTest("indirectly through .packages", files, (Uri directory, loader) async { - Uri file = directory.resolve(".packages"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve(".packages"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -183,8 +177,8 @@ main() { "pheldagriff": packageConfigFile, }, }, (Uri directory, loader) async { - Uri file = directory.resolve("subdir/pheldagriff"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve("subdir/pheldagriff"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -194,8 +188,8 @@ main() { ".packages": packageConfigFile, }, }, (Uri directory, loader) async { - Uri file = directory.resolve("subdir/.packages"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve("subdir/.packages"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -203,8 +197,8 @@ main() { loaderTest(".packages", { ".packages": packagesFile, }, (Uri directory, loader) async { - Uri file = directory.resolve(".packages"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve(".packages"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 1); validatePackagesFile(config, directory); }); @@ -212,22 +206,22 @@ main() { loaderTest(".packages non-default name", { "pheldagriff": packagesFile, }, (Uri directory, loader) async { - Uri file = directory.resolve("pheldagriff"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve("pheldagriff"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 1); validatePackagesFile(config, directory); }); loaderTest("no config found", {}, (Uri directory, loader) { - Uri file = directory.resolve("anyname"); + var file = directory.resolve("anyname"); expect(() => loadPackageConfigUri(file, loader: loader), throwsA(isA())); }); loaderTest("no config found, handle error", {}, (Uri directory, loader) async { - Uri file = directory.resolve("anyname"); - bool hadError = false; + var file = directory.resolve("anyname"); + var hadError = false; await loadPackageConfigUri(file, loader: loader, onError: expectAsync1((error) { @@ -240,7 +234,7 @@ main() { loaderTest("specified file syntax error", { "anyname": "syntax error", }, (Uri directory, loader) { - Uri file = directory.resolve("anyname"); + var file = directory.resolve("anyname"); expect(() => loadPackageConfigUri(file, loader: loader), throwsFormatException); }); @@ -248,8 +242,8 @@ main() { loaderTest("specified file syntax error", { "anyname": "syntax error", }, (Uri directory, loader) async { - Uri file = directory.resolve("anyname"); - bool hadError = false; + var file = directory.resolve("anyname"); + var hadError = false; await loadPackageConfigUri(file, loader: loader, onError: expectAsync1((error) { @@ -266,8 +260,8 @@ main() { "package_config.json": packageConfigFile, }, }, (Uri directory, loader) async { - Uri file = directory.resolve("anyname"); - PackageConfig config = await loadPackageConfigUri(file, loader: loader); + var file = directory.resolve("anyname"); + var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); @@ -276,7 +270,7 @@ main() { loaderTest("file syntax error with {", { ".packages": "{syntax error", }, (Uri directory, loader) async { - Uri file = directory.resolve(".packages"); + var file = directory.resolve(".packages"); var hadError = false; await loadPackageConfigUri(file, loader: loader, diff --git a/pkgs/package_config/test/legacy/all.dart b/pkgs/package_config/test/legacy/all.dart new file mode 100644 index 000000000..22e2e4f9e --- /dev/null +++ b/pkgs/package_config/test/legacy/all.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2015, 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. + +@deprecated +library package_config.all_test; + +import "package:test/test.dart"; + +import "discovery_analysis_test.dart" as discovery_analysis; +import "discovery_test.dart" as discovery; +import "parse_test.dart" as parse; +import "parse_write_test.dart" as parse_write; + +void main() { + group("parse:", parse.main); + group("discovery:", discovery.main); + group("discovery-analysis:", discovery_analysis.main); + group("parse/write:", parse_write.main); +} diff --git a/pkgs/package_config/test/legacy/discovery_analysis_test.dart b/pkgs/package_config/test/legacy/discovery_analysis_test.dart new file mode 100644 index 000000000..7d08f7b92 --- /dev/null +++ b/pkgs/package_config/test/legacy/discovery_analysis_test.dart @@ -0,0 +1,127 @@ +// Copyright (c) 2015, 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. + +@deprecated +library package_config.discovery_analysis_test; + +import "dart:async"; +import "dart:io"; + +import "package:package_config/discovery_analysis.dart"; +import "package:package_config/packages.dart"; +import "package:path/path.dart" as path; +import "package:test/test.dart"; + +void main() { + fileTest("basic", { + ".packages": packagesFile, + "foo": {".packages": packagesFile}, + "bar": { + "packages": {"foo": {}, "bar": {}, "baz": {}} + }, + "baz": {} + }, (Directory directory) { + var dirUri = Uri.directory(directory.path); + var ctx = PackageContext.findAll(directory); + var root = ctx[directory]; + expect(root, same(ctx)); + validatePackagesFile(root.packages, dirUri); + var fooDir = sub(directory, "foo"); + var foo = ctx[fooDir]; + expect(identical(root, foo), isFalse); + validatePackagesFile(foo.packages, dirUri.resolve("foo/")); + var barDir = sub(directory, "bar"); + var bar = ctx[sub(directory, "bar")]; + validatePackagesDir(bar.packages, dirUri.resolve("bar/")); + var barbar = ctx[sub(barDir, "bar")]; + expect(barbar, same(bar)); // inherited. + var baz = ctx[sub(directory, "baz")]; + expect(baz, same(root)); // inherited. + + var map = ctx.asMap(); + expect(map.keys.map((dir) => dir.path), + unorderedEquals([directory.path, fooDir.path, barDir.path])); + return null; + }); +} + +Directory sub(Directory parent, String dirName) { + return Directory(path.join(parent.path, dirName)); +} + +const packagesFile = """ +# A comment +foo:file:///dart/packages/foo/ +bar:http://example.com/dart/packages/bar/ +baz:packages/baz/ +"""; + +void validatePackagesFile(Packages resolver, Uri location) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +} + +void validatePackagesDir(Packages resolver, Uri location) { + // Expect three packages: foo, bar and baz + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(location.resolve("packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(location.resolve("packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + if (location.scheme == "file") { + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); + } else { + expect(() => resolver.packages, throwsUnsupportedError); + } +} + +Uri pkg(String packageName, String packagePath) { + var path; + if (packagePath.startsWith('/')) { + path = "$packageName$packagePath"; + } else { + path = "$packageName/$packagePath"; + } + return Uri(scheme: "package", path: path); +} + +/// Create a directory structure from [description] and run [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void fileTest( + String name, Map description, Future fileTest(Directory directory)) { + group("file-test", () { + var tempDir = Directory.systemTemp.createTempSync("file-test"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(tempDir)); + }); +} + +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + if (content is Map) { + var subDir = Directory(path.join(target.path, name)); + subDir.createSync(); + _createFiles(subDir, content); + } else { + var file = File(path.join(target.path, name)); + file.writeAsStringSync(content, flush: true); + } + }); +} diff --git a/pkgs/package_config/test/legacy/discovery_test.dart b/pkgs/package_config/test/legacy/discovery_test.dart new file mode 100644 index 000000000..684abcb4a --- /dev/null +++ b/pkgs/package_config/test/legacy/discovery_test.dart @@ -0,0 +1,328 @@ +// Copyright (c) 2015, 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. + +@deprecated +library package_config.discovery_test; + +import "dart:async"; +import "dart:io"; +import "package:test/test.dart"; +import "package:package_config/packages.dart"; +import "package:package_config/discovery.dart"; +import "package:path/path.dart" as path; + +const packagesFile = """ +# A comment +foo:file:///dart/packages/foo/ +bar:http://example.com/dart/packages/bar/ +baz:packages/baz/ +"""; + +void validatePackagesFile(Packages resolver, Uri location) { + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); +} + +void validatePackagesDir(Packages resolver, Uri location) { + // Expect three packages: foo, bar and baz + expect(resolver, isNotNull); + expect(resolver.resolve(pkg("foo", "bar/baz")), + equals(location.resolve("packages/foo/bar/baz"))); + expect(resolver.resolve(pkg("bar", "baz/qux")), + equals(location.resolve("packages/bar/baz/qux"))); + expect(resolver.resolve(pkg("baz", "qux/foo")), + equals(location.resolve("packages/baz/qux/foo"))); + if (location.scheme == "file") { + expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); + } else { + expect(() => resolver.packages, throwsUnsupportedError); + } +} + +Uri pkg(String packageName, String packagePath) { + var path; + if (packagePath.startsWith('/')) { + path = "$packageName$packagePath"; + } else { + path = "$packageName/$packagePath"; + } + return Uri(scheme: "package", path: path); +} + +void main() { + generalTest(".packages", { + ".packages": packagesFile, + "script.dart": "main(){}", + "packages": {"shouldNotBeFound": {}} + }, (Uri location) async { + Packages resolver; + resolver = await findPackages(location); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + var specificDiscovery = (location.scheme == "file") + ? findPackagesFromFile + : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesFile(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesFile(resolver, location); + }); + + generalTest("packages/", { + "packages": {"foo": {}, "bar": {}, "baz": {}}, + "script.dart": "main(){}" + }, (Uri location) async { + Packages resolver; + var isFile = (location.scheme == "file"); + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + var specificDiscovery = + isFile ? findPackagesFromFile : findPackagesFromNonFile; + resolver = await specificDiscovery(location); + validatePackagesDir(resolver, location); + resolver = await specificDiscovery(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + generalTest("underscore packages", { + "packages": {"_foo": {}} + }, (Uri location) async { + var resolver = await findPackages(location); + expect(resolver.resolve(pkg("_foo", "foo.dart")), + equals(location.resolve("packages/_foo/foo.dart"))); + }); + + fileTest(".packages recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Uri location) async { + Packages resolver; + resolver = await findPackages(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = await findPackages(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromFile(location.resolve("subdir/")); + validatePackagesFile(resolver, location); + resolver = + await findPackagesFromFile(location.resolve("subdir/script.dart")); + validatePackagesFile(resolver, location); + }); + + httpTest(".packages not recursive", { + ".packages": packagesFile, + "subdir": {"script.dart": "main(){}"} + }, (Uri location) async { + Packages resolver; + var subdir = location.resolve("subdir/"); + resolver = await findPackages(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackages(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir); + validatePackagesDir(resolver, subdir); + resolver = await findPackagesFromNonFile(subdir.resolve("script.dart")); + validatePackagesDir(resolver, subdir); + }); + + fileTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { + // A file: location with no .packages or packages returns + // Packages.noPackages. + Packages resolver; + resolver = await findPackages(location); + expect(resolver, same(Packages.noPackages)); + resolver = await findPackages(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location); + expect(resolver, same(Packages.noPackages)); + resolver = findPackagesFromFile(location.resolve("script.dart")); + expect(resolver, same(Packages.noPackages)); + }); + + httpTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location); + validatePackagesDir(resolver, location); + resolver = await findPackages(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart")); + validatePackagesDir(resolver, location); + }); + + test(".packages w/ loader", () async { + var location = Uri.parse("krutch://example.com/path/"); + Future> loader(Uri file) async { + if (file.path.endsWith(".packages")) { + return packagesFile.codeUnits; + } + throw "not found"; + } + + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = + await findPackages(location.resolve("script.dart"), loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesFile(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader: loader); + validatePackagesFile(resolver, location); + }); + + test("no packages w/ loader", () async { + var location = Uri.parse("krutch://example.com/path/"); + Future> loader(Uri file) async { + throw "not found"; + } + + // A non-file: location with no .packages or packages/: + // Assumes a packages dir exists, and resolves relative to that. + Packages resolver; + resolver = await findPackages(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = + await findPackages(location.resolve("script.dart"), loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location, loader: loader); + validatePackagesDir(resolver, location); + resolver = await findPackagesFromNonFile(location.resolve("script.dart"), + loader: loader); + validatePackagesDir(resolver, location); + }); + + generalTest("loadPackagesFile", {".packages": packagesFile}, + (Uri directory) async { + var file = directory.resolve(".packages"); + var resolver = await loadPackagesFile(file); + validatePackagesFile(resolver, file); + }); + + generalTest( + "loadPackagesFile non-default name", {"pheldagriff": packagesFile}, + (Uri directory) async { + var file = directory.resolve("pheldagriff"); + var resolver = await loadPackagesFile(file); + validatePackagesFile(resolver, file); + }); + + test("loadPackagesFile w/ loader", () async { + Future> loader(Uri uri) async => packagesFile.codeUnits; + var file = Uri.parse("krutz://example.com/.packages"); + var resolver = await loadPackagesFile(file, loader: loader); + validatePackagesFile(resolver, file); + }); + + generalTest("loadPackagesFile not found", {}, (Uri directory) async { + var file = directory.resolve(".packages"); + expect( + loadPackagesFile(file), + throwsA(anyOf( + TypeMatcher(), TypeMatcher()))); + }); + + generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, + (Uri directory) async { + var file = directory.resolve(".packages"); + expect(loadPackagesFile(file), throwsFormatException); + }); + + generalTest("getPackagesDir", { + "packages": {"foo": {}, "bar": {}, "baz": {}} + }, (Uri directory) async { + var packages = directory.resolve("packages/"); + var resolver = getPackagesDirectory(packages); + var resolved = resolver.resolve(pkg("foo", "flip/flop")); + expect(resolved, packages.resolve("foo/flip/flop")); + }); +} + +/// Create a directory structure from [description] and run [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void fileTest(String name, Map description, Future fileTest(Uri directory)) { + group("file-test", () { + var tempDir = Directory.systemTemp.createTempSync("file-test"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(Uri.file(path.join(tempDir.path, ".")))); + }); +} + +/// HTTP-server the directory structure from [description] and run [htpTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a sub-dir, otherwise it's a file and the value is the content +/// as a string. +void httpTest(String name, Map description, Future httpTest(Uri directory)) { + group("http-test", () { + var serverSub; + var uri; + setUp(() { + return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) { + uri = Uri( + scheme: "http", host: "127.0.0.1", port: server.port, path: "/"); + serverSub = server.listen((HttpRequest request) { + // No error handling. + var path = request.uri.path; + if (path.startsWith('/')) path = path.substring(1); + if (path.endsWith('/')) path = path.substring(0, path.length - 1); + var parts = path.split('/'); + dynamic fileOrDir = description; + for (var i = 0; i < parts.length; i++) { + fileOrDir = fileOrDir[parts[i]]; + if (fileOrDir == null) { + request.response.statusCode = 404; + request.response.close(); + return; + } + } + request.response.write(fileOrDir); + request.response.close(); + }); + }); + }); + tearDown(() => serverSub.cancel()); + test(name, () => httpTest(uri)); + }); +} + +void generalTest(String name, Map description, Future action(Uri location)) { + fileTest(name, description, action); + httpTest(name, description, action); +} + +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + if (content is Map) { + var subDir = Directory(path.join(target.path, name)); + subDir.createSync(); + _createFiles(subDir, content); + } else { + var file = File(path.join(target.path, name)); + file.writeAsStringSync(content, flush: true); + } + }); +} diff --git a/pkgs/package_config/test/legacy/parse_test.dart b/pkgs/package_config/test/legacy/parse_test.dart new file mode 100644 index 000000000..b9cf1f8fd --- /dev/null +++ b/pkgs/package_config/test/legacy/parse_test.dart @@ -0,0 +1,246 @@ +// Copyright (c) 2015, 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. + +@deprecated +library package_config.parse_test; + +import "package:package_config/packages.dart"; +import "package:package_config/packages_file.dart" show parse; +import "package:package_config/src/packages_impl.dart"; +import "package:test/test.dart"; + +void main() { + var base = Uri.parse("file:///one/two/three/packages.map"); + test("empty", () { + var packages = doParse(emptySample, base); + expect(packages.asMap(), isEmpty); + }); + test("comment only", () { + var packages = doParse(commentOnlySample, base); + expect(packages.asMap(), isEmpty); + }); + test("empty lines only", () { + var packages = doParse(emptyLinesSample, base); + expect(packages.asMap(), isEmpty); + }); + + test("empty lines only", () { + var packages = doParse(emptyLinesSample, base); + expect(packages.asMap(), isEmpty); + }); + + test("single", () { + var packages = doParse(singleRelativeSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single no slash", () { + var packages = doParse(singleRelativeSampleNoSlash, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single no newline", () { + var packages = doParse(singleRelativeSampleNoNewline, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("single absolute authority", () { + var packages = doParse(singleAbsoluteSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); + }); + + test("single empty path", () { + var packages = doParse(singleEmptyPathSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.replace(path: "${base.path}/bar/baz.dart"))); + }); + + test("single absolute path", () { + var packages = doParse(singleAbsolutePathSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.replace(path: "/test/bar/baz.dart"))); + }); + + test("multiple", () { + var packages = doParse(multiRelativeSample, base); + expect(packages.packages.toList()..sort(), equals(["bar", "foo"])); + expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), + equals(base.resolve("../test2/").resolve("foo/baz.dart"))); + }); + + test("dot-dot 1", () { + var packages = doParse(singleRelativeSample, base); + expect(packages.packages.toList(), equals(["foo"])); + expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("all valid chars can be used in URI segment", () { + var packages = doParse(allValidCharsSample, base); + expect(packages.packages.toList(), equals([allValidChars])); + expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), + equals(base.resolve("../test/").resolve("bar/baz.dart"))); + }); + + test("no invalid chars accepted", () { + var map = {}; + for (var i = 0; i < allValidChars.length; i++) { + map[allValidChars.codeUnitAt(i)] = true; + } + for (var i = 0; i <= 255; i++) { + if (map[i] == true) continue; + var char = String.fromCharCode(i); + expect(() => doParse("x${char}x:x", null), + anyOf(throwsNoSuchMethodError, throwsFormatException)); + } + }); + + test("no escapes", () { + expect(() => doParse("x%41x:x", base), throwsFormatException); + }); + + test("same name twice", () { + expect( + () => doParse(singleRelativeSample * 2, base), throwsFormatException); + }); + + test("disallow default package", () { + expect(() => doParse(":foo", base, allowDefaultPackage: false), + throwsFormatException); + }); + + test("allow default package", () { + var packages = doParse(":foo", base, allowDefaultPackage: true); + expect(packages.defaultPackageName, "foo"); + }); + + test("allow default package name with dot", () { + var packages = doParse(":foo.bar", base, allowDefaultPackage: true); + expect(packages.defaultPackageName, "foo.bar"); + }); + + test("not two default packages", () { + expect(() => doParse(":foo\n:bar", base, allowDefaultPackage: true), + throwsFormatException); + }); + + test("default package invalid package name", () { + // Not a valid *package name*. + expect(() => doParse(":foo/bar", base, allowDefaultPackage: true), + throwsFormatException); + }); + + group("metadata", () { + var packages = doParse( + ":foo\n" + "foo:foo#metafoo=1\n" + "bar:bar#metabar=2\n" + "baz:baz\n" + "qux:qux#metaqux1=3&metaqux2=4\n", + base, + allowDefaultPackage: true); + test("non-existing", () { + // non-package name. + expect(packages.packageMetadata("///", "f"), null); + expect(packages.packageMetadata("", "f"), null); + // unconfigured package name. + expect(packages.packageMetadata("absent", "f"), null); + // package name without that metadata + expect(packages.packageMetadata("foo", "notfoo"), null); + }); + test("lookup", () { + expect(packages.packageMetadata("foo", "metafoo"), "1"); + expect(packages.packageMetadata("bar", "metabar"), "2"); + expect(packages.packageMetadata("qux", "metaqux1"), "3"); + expect(packages.packageMetadata("qux", "metaqux2"), "4"); + }); + test("by library URI", () { + expect( + packages.libraryMetadata( + Uri.parse("package:foo/index.dart"), "metafoo"), + "1"); + expect( + packages.libraryMetadata( + Uri.parse("package:bar/index.dart"), "metabar"), + "2"); + expect( + packages.libraryMetadata( + Uri.parse("package:qux/index.dart"), "metaqux1"), + "3"); + expect( + packages.libraryMetadata( + Uri.parse("package:qux/index.dart"), "metaqux2"), + "4"); + }); + test("by default package", () { + expect( + packages.libraryMetadata( + Uri.parse("file:///whatever.dart"), "metafoo"), + "1"); + }); + }); + + for (var invalidSample in invalid) { + test("invalid '$invalidSample'", () { + var result; + try { + result = doParse(invalidSample, base); + } on FormatException { + // expected + return; + } + fail("Resolved to $result"); + }); + } +} + +Packages doParse(String sample, Uri baseUri, + {bool allowDefaultPackage = false}) { + var map = parse(sample.codeUnits, baseUri, + allowDefaultPackage: allowDefaultPackage); + return MapPackages(map); +} + +// Valid samples. +var emptySample = ""; +var commentOnlySample = "# comment only\n"; +var emptyLinesSample = "\n\n\r\n"; +var singleRelativeSample = "foo:../test/\n"; +var singleRelativeSampleNoSlash = "foo:../test\n"; +var singleRelativeSampleNoNewline = "foo:../test/"; +var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; +var singleEmptyPathSample = "foo:\n"; +var singleAbsolutePathSample = "foo:/test/\n"; +var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; +// All valid path segment characters in an URI. +var allValidChars = r"!$&'()*+,-.0123456789;=" + r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; + +var allValidCharsSample = "${allValidChars}:../test/\n"; + +// Invalid samples. +var invalid = [ + ":baz.dart", // empty. + "foobar=baz.dart", // no colon (but an equals, which is not the same) + ".:../test/", // dot segment + "..:../test/", // dot-dot segment + "...:../test/", // dot-dot-dot segment + "foo/bar:../test/", // slash in name + "/foo:../test/", // slash at start of name + "?:../test/", // invalid characters. + "[:../test/", // invalid characters. + "x#:../test/", // invalid characters. +]; diff --git a/pkgs/package_config/test/legacy/parse_write_test.dart b/pkgs/package_config/test/legacy/parse_write_test.dart new file mode 100644 index 000000000..a51ced1ba --- /dev/null +++ b/pkgs/package_config/test/legacy/parse_write_test.dart @@ -0,0 +1,133 @@ +// Copyright (c) 2015, 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. + +@deprecated +library package_config.parse_write_test; + +import "dart:convert" show utf8; +import "package:package_config/packages_file.dart"; +import "package:test/test.dart"; + +void main() { + void testBase(baseDirString) { + var baseDir = Uri.parse(baseDirString); + group("${baseDir.scheme} base", () { + var packagesFile = baseDir.resolve(".packages"); + + void roundTripTest(String name, Map map) { + group(name, () { + test("write with no baseUri", () { + var content = writeToString(map).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + + test("write with base directory", () { + var content = writeToString(map, baseUri: baseDir).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + + test("write with base .packages file", () { + var content = writeToString(map, baseUri: packagesFile).codeUnits; + var resultMap = parse(content, packagesFile); + expect(resultMap, map); + }); + + test("write with defaultPackageName", () { + var content = writeToString( + {'': Uri.parse('my_pkg')}..addAll(map), + allowDefaultPackage: true, + ).codeUnits; + var resultMap = parse( + content, + packagesFile, + allowDefaultPackage: true, + ); + expect(resultMap[''].toString(), 'my_pkg'); + expect( + resultMap, + {'': Uri.parse('my_pkg')}..addAll(map), + ); + }); + + test("write with defaultPackageName (utf8)", () { + var content = utf8.encode(writeToString( + {'': Uri.parse('my_pkg')}..addAll(map), + allowDefaultPackage: true, + )); + var resultMap = parse( + content, + packagesFile, + allowDefaultPackage: true, + ); + expect(resultMap[''].toString(), 'my_pkg'); + expect( + resultMap, + {'': Uri.parse('my_pkg')}..addAll(map), + ); + }); + }); + } + + var lowerDir = baseDir.resolve("path3/path4/"); + var higherDir = baseDir.resolve("../"); + var parallelDir = baseDir.resolve("../path3/"); + var rootDir = baseDir.resolve("/"); + var fileDir = Uri.parse("file:///path1/part2/"); + var httpDir = Uri.parse("http://example.com/path1/path2/"); + var otherDir = Uri.parse("other:/path1/path2/"); + + roundTripTest("empty", {}); + roundTripTest("lower directory", {"foo": lowerDir}); + roundTripTest("higher directory", {"foo": higherDir}); + roundTripTest("parallel directory", {"foo": parallelDir}); + roundTripTest("same directory", {"foo": baseDir}); + roundTripTest("root directory", {"foo": rootDir}); + roundTripTest("file directory", {"foo": fileDir}); + roundTripTest("http directory", {"foo": httpDir}); + roundTripTest("other scheme directory", {"foo": otherDir}); + roundTripTest("multiple same-type directories", + {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); + roundTripTest("multiple scheme directories", + {"foo": fileDir, "bar": httpDir, "baz": otherDir}); + roundTripTest("multiple scheme directories and mutliple same type", { + "foo": fileDir, + "bar": httpDir, + "baz": otherDir, + "qux": lowerDir, + "hip": higherDir, + "dep": parallelDir + }); + }); + } + + testBase("file:///base1/base2/"); + testBase("http://example.com/base1/base2/"); + testBase("other:/base1/base2/"); + + // Check that writing adds the comment. + test("write preserves comment", () { + var comment = "comment line 1\ncomment line 2\ncomment line 3"; + var result = writeToString({}, comment: comment); + // Comment with "# " before each line and "\n" after last. + var expectedComment = + "# comment line 1\n# comment line 2\n# comment line 3\n"; + expect(result, startsWith(expectedComment)); + }); +} + +String writeToString( + Map map, { + Uri baseUri, + String comment, + bool allowDefaultPackage = false, +}) { + var buffer = StringBuffer(); + write(buffer, map, + baseUri: baseUri, + comment: comment, + allowDefaultPackage: allowDefaultPackage); + return buffer.toString(); +} diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index d9430953c..367b64384 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -3,10 +3,11 @@ // BSD-style license that can be found in the LICENSE file. import "dart:convert"; +import 'dart:typed_data'; import "package:test/test.dart"; -import "package:package_config/package_config.dart"; +import "package:package_config/package_config_types.dart"; import "package:package_config/src/packages_file.dart" as packages; import "package:package_config/src/package_config_json.dart"; import "src/util.dart"; @@ -48,14 +49,14 @@ void main() { group("invalid", () { var baseFile = Uri.file("/tmp/file.dart"); - testThrows(String name, String content) { + void testThrows(String name, String content) { test(name, () { expect( () => packages.parse(utf8.encode(content), baseFile, throwError), throwsA(TypeMatcher())); }); test(name + ", handle error", () { - bool hadError = false; + var hadError = false; packages.parse(utf8.encode(content), baseFile, (error) { hadError = true; expect(error, isA()); @@ -256,7 +257,7 @@ void main() { }); group("invalid", () { - testThrows(String name, String source) { + void testThrows(String name, String source) { test(name, () { expect( () => parsePackageConfigBytes(utf8.encode(source), @@ -364,11 +365,79 @@ void main() { "same roots", '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); testThrows( - // The root of bar is inside the package root of foo. - "inside lib", + // The root of bar is inside the root of foo, + // but the package root of foo is inside the root of bar. + "between root and lib", '{$cfg,"packages":[' - '{"name":"foo","rootUri":"/foo/","packageUri":"lib/"},' - '{"name":"bar","rootUri":"/foo/lib/qux/"}]}'); + '{"name":"foo","rootUri":"/foo/","packageUri":"bar/lib/"},' + '{"name":"bar","rootUri":"/foo/bar/"},"packageUri":"baz/lib"]}'); }); }); + + group("factories", () { + void testConfig(String name, PackageConfig config, PackageConfig expected) { + group(name, () { + test("structure", () { + expect(config.version, expected.version); + var expectedPackages = {for (var p in expected.packages) p.name}; + var actualPackages = {for (var p in config.packages) p.name}; + expect(actualPackages, expectedPackages); + }); + for (var package in config.packages) { + var name = package.name; + test("package $name", () { + var expectedPackage = expected[name]; + expect(expectedPackage, isNotNull); + expect(package.root, expectedPackage.root, reason: "root"); + expect(package.packageUriRoot, expectedPackage.packageUriRoot, + reason: "package root"); + expect(package.languageVersion, expectedPackage.languageVersion, + reason: "languageVersion"); + }); + } + }); + } + + var configText = """ + {"configVersion": 2, "packages": [ + { + "name": "foo", + "rootUri": "foo/", + "packageUri": "bar/", + "languageVersion": "1.2" + } + ]} + """; + var baseUri = Uri.parse("file:///start/"); + var config = PackageConfig([ + Package("foo", Uri.parse("file:///start/foo/"), + packageUriRoot: Uri.parse("file:///start/foo/bar/"), + languageVersion: LanguageVersion(1, 2)) + ]); + testConfig( + "string", PackageConfig.parseString(configText, baseUri), config); + testConfig( + "bytes", + PackageConfig.parseBytes( + Uint8List.fromList(configText.codeUnits), baseUri), + config); + testConfig("json", PackageConfig.parseJson(jsonDecode(configText), baseUri), + config); + + baseUri = Uri.parse("file:///start2/"); + config = PackageConfig([ + Package("foo", Uri.parse("file:///start2/foo/"), + packageUriRoot: Uri.parse("file:///start2/foo/bar/"), + languageVersion: LanguageVersion(1, 2)) + ]); + testConfig( + "string2", PackageConfig.parseString(configText, baseUri), config); + testConfig( + "bytes2", + PackageConfig.parseBytes( + Uint8List.fromList(configText.codeUnits), baseUri), + config); + testConfig("json2", + PackageConfig.parseJson(jsonDecode(configText), baseUri), config); + }); } diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 95670bdbb..2b91b2130 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -18,7 +18,7 @@ import "package:package_config/src/util.dart"; void fileTest(String name, Map description, void fileTest(Directory directory)) { group("file-test", () { - Directory tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); + var tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); setUp(() { _createFiles(tempDir, description); }); @@ -67,7 +67,7 @@ File dirFile(Directory directory, String fileName) => Uri pkg(String packageName, String packagePath) { var path = "$packageName${packagePath.startsWith('/') ? "" : "/"}$packagePath"; - return new Uri(scheme: "package", path: path); + return Uri(scheme: "package", path: path); } // Remove if not used. @@ -91,13 +91,13 @@ ${packages.map((nu) => """ /// as a string. void loaderTest(String name, Map description, void loaderTest(Uri root, Future loader(Uri uri))) { - Uri root = Uri(scheme: "test", path: "/"); + var root = Uri(scheme: "test", path: "/"); Future loader(Uri uri) async { var path = uri.path; if (!uri.isScheme("test") || !path.startsWith("/")) return null; var parts = path.split("/"); dynamic value = description; - for (int i = 1; i < parts.length; i++) { + for (var i = 1; i < parts.length; i++) { if (value is! Map) return null; value = value[parts[i]]; } From af58162f9d26235eed94104c4a7c2c522ac68b1c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 00:09:03 -0800 Subject: [PATCH 134/281] Tweak readme (dart-lang/package_config#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Tweak readme Remove gratuitous title Move badges to top, as is tradition * Update README.md Remove issue/feature request blurb – this is automatically done on the pub site! --- pkgs/package_config/README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index ec51f6ea7..5a76a7ab1 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,4 +1,5 @@ -# package_config +[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) +[![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). @@ -15,11 +16,3 @@ The primary libraries are The package includes deprecated backwards compatible functionality to work with the `.packages` file. This functionality will not be maintained, and will be removed in a future version of this package. - -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) - -## Features and bugs - -Please file feature requests and bugs at the [issue tracker][tracker]. - -[tracker]: https://github.com/dart-lang/package_config/issues From b69e8ac948775b58bffe2f119eb1e88ce754cc56 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 26 Feb 2020 09:10:03 +0100 Subject: [PATCH 135/281] Remove 1.2.0 from changelog. That version was never released. --- pkgs/package_config/CHANGELOG.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index c6caf4d6e..a86d1a54f 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -5,11 +5,6 @@ version, as well as the, now deprecated, version 1 functionality. When we release 2.0.0, the deprectated functionality will be removed. -## 1.2.0 - -- Added support for writing default-package entries. -- Fixed bug when writing `Uri`s containing a fragment. - ## 1.1.0 - Allow parsing files with default-package entries and metadata. From 267c75ab3c875d335cf294a10de340713a62ac4a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 08:50:41 -0800 Subject: [PATCH 136/281] Remove pubspec author, fix URL in readme (dart-lang/package_config#71) --- pkgs/package_config/README.md | 2 +- pkgs/package_config/pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 5a76a7ab1..b47a6825b 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,5 +1,5 @@ [![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) -[![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dartlang.org/packages/package_config) +[![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 20a39c767..0eaeeda93 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,7 +1,6 @@ name: package_config version: 1.9.0-dev description: Support for working with Package Configuration files. -author: Dart Team homepage: https://github.com/dart-lang/package_config environment: From 45477a6a7d1f62d4c4f97efa0e45bc685321e530 Mon Sep 17 00:00:00 2001 From: Lasse Nielsen Date: Wed, 26 Feb 2020 19:18:52 +0000 Subject: [PATCH 137/281] Add missing dependency on package:path. --- pkgs/package_config/pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 0eaeeda93..c37dda616 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -6,6 +6,9 @@ homepage: https://github.com/dart-lang/package_config environment: sdk: '>=2.7.0 <3.0.0' +dependencies: + path: ^1.6.4 + dev_dependencies: test: ^1.6.4 matcher: ^0.12.5 From 48ab5081081ff91362dde900a1f0cbea9138e150 Mon Sep 17 00:00:00 2001 From: Lasse Nielsen Date: Wed, 26 Feb 2020 19:23:20 +0000 Subject: [PATCH 138/281] Add another missing dependency. --- pkgs/package_config/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index c37dda616..651dbec28 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: path: ^1.6.4 + charcode: ^1.1.0 dev_dependencies: test: ^1.6.4 From 6c4b1492ffbdea9becd3acf41b3b43e2ff06962b Mon Sep 17 00:00:00 2001 From: Lasse Nielsen Date: Wed, 26 Feb 2020 19:31:03 +0000 Subject: [PATCH 139/281] Set version to 1.9.0 (no -dev) for release. --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 651dbec28..abaddd9e9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.9.0-dev +version: 1.9.0 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config From 6d7290406dd7f7416212eeb4361405b0b2d1f32a Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 26 Feb 2020 14:30:43 -0800 Subject: [PATCH 140/281] move io utils to their own library, release 1.9.1 (dart-lang/package_config#74) --- pkgs/package_config/.travis.yml | 5 + pkgs/package_config/CHANGELOG.md | 5 + pkgs/package_config/lib/src/discovery.dart | 2 +- .../lib/src/package_config_io.dart | 1 + .../lib/src/packages_io_impl.dart | 2 +- pkgs/package_config/lib/src/util.dart | 99 ---------------- pkgs/package_config/lib/src/util_io.dart | 106 ++++++++++++++++++ pkgs/package_config/pubspec.yaml | 5 +- pkgs/package_config/test/discovery_test.dart | 2 + .../test/discovery_uri_test.dart | 1 + .../test/legacy/discovery_analysis_test.dart | 1 + .../test/legacy/discovery_test.dart | 1 + pkgs/package_config/test/src/util.dart | 56 --------- pkgs/package_config/test/src/util_io.dart | 62 ++++++++++ 14 files changed, 190 insertions(+), 158 deletions(-) create mode 100644 pkgs/package_config/lib/src/util_io.dart create mode 100644 pkgs/package_config/test/src/util_io.dart diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index 655bf3dc1..09fc296c2 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -7,6 +7,11 @@ dart_task: - dartfmt - dartanalyzer: --fatal-warnings . +matrix: + include: + - dart: dev + script: pub run build_runner test -- -p chrome + # Only building master means that we don't run two builds for each pull request. branches: only: [master] diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index a86d1a54f..1cd45d007 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.9.1 + +- Remove accidental transitive import of `dart:io` from entrypoints that are + supposed to be cross-platform compatible. + ## 1.9.0 - Based on new JSON file format with more content. diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 5d3172f26..8ac6a0128 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -11,7 +11,7 @@ import "errors.dart"; import "package_config_impl.dart"; import "package_config_json.dart"; import "packages_file.dart" as packages_file; -import "util.dart" show defaultLoader, pathJoin; +import "util_io.dart" show defaultLoader, pathJoin; final Uri packageConfigJsonPath = Uri(path: ".dart_tool/package_config.json"); final Uri dotPackagesPath = Uri(path: ".packages"); diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index d59972f9a..954be6b1e 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -14,6 +14,7 @@ import "package_config_impl.dart"; import "package_config_json.dart"; import "packages_file.dart" as packages_file; import "util.dart"; +import "util_io.dart"; /// Reads a package configuration file. /// diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart index b2277e7e0..c623f4d5d 100644 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ b/pkgs/package_config/lib/src/packages_io_impl.dart @@ -12,7 +12,7 @@ import "dart:io" show Directory; import "packages_impl.dart"; -import "util.dart"; +import "util_io.dart"; /// A [Packages] implementation based on a local directory. class FilePackagesDirectoryPackages extends PackagesBase { diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 548f61d98..50b140fa0 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -5,9 +5,6 @@ /// Utility methods used by more than one library in the package. library package_config.util; -import 'dart:io'; -import 'dart:typed_data'; - import "errors.dart"; // All ASCII characters that are valid in a package name, with space @@ -215,102 +212,6 @@ Uri relativizeUri(Uri uri, Uri /*?*/ baseUri) { } } -Future defaultLoader(Uri uri) async { - if (uri.isScheme("file")) { - var file = File.fromUri(uri); - try { - return file.readAsBytes(); - } catch (_) { - return null; - } - } - if (uri.isScheme("http") || uri.isScheme("https")) { - return _httpGet(uri); - } - throw UnsupportedError("Default URI unsupported scheme: $uri"); -} - -Future _httpGet(Uri uri) async { - assert(uri.isScheme("http") || uri.isScheme("https")); - var client = HttpClient(); - var request = await client.getUrl(uri); - var response = await request.close(); - if (response.statusCode != HttpStatus.ok) { - return null; - } - var splitContent = await response.toList(); - var totalLength = 0; - if (splitContent.length == 1) { - var part = splitContent[0]; - if (part is Uint8List) { - return part; - } - } - for (var list in splitContent) { - totalLength += list.length; - } - var result = Uint8List(totalLength); - var offset = 0; - for (Uint8List contentPart in splitContent) { - result.setRange(offset, offset + contentPart.length, contentPart); - offset += contentPart.length; - } - return result; -} - -/// The file name of a path. -/// -/// The file name is everything after the last occurrence of -/// [Platform.pathSeparator], or the entire string if no -/// path separator occurs in the string. -String fileName(String path) { - var separator = Platform.pathSeparator; - var lastSeparator = path.lastIndexOf(separator); - if (lastSeparator < 0) return path; - return path.substring(lastSeparator + separator.length); -} - -/// The directory name of a path. -/// -/// The directory name is everything before the last occurrence of -/// [Platform.pathSeparator], or the empty string if no -/// path separator occurs in the string. -String dirName(String path) { - var separator = Platform.pathSeparator; - var lastSeparator = path.lastIndexOf(separator); - if (lastSeparator < 0) return ""; - return path.substring(0, lastSeparator); -} - -/// Join path parts with the [Platform.pathSeparator]. -/// -/// If a part ends with a path separator, then no extra separator is -/// inserted. -String pathJoin(String part1, String part2, [String part3]) { - var separator = Platform.pathSeparator; - var separator1 = part1.endsWith(separator) ? "" : separator; - if (part3 == null) { - return "$part1$separator1$part2"; - } - var separator2 = part2.endsWith(separator) ? "" : separator; - return "$part1$separator1$part2$separator2$part3"; -} - -/// Join an unknown number of path parts with [Platform.pathSeparator]. -/// -/// If a part ends with a path separator, then no extra separator is -/// inserted. -String pathJoinAll(Iterable parts) { - var buffer = StringBuffer(); - var separator = ""; - for (var part in parts) { - buffer..write(separator)..write(part); - separator = - part.endsWith(Platform.pathSeparator) ? "" : Platform.pathSeparator; - } - return buffer.toString(); -} - // Character constants used by this package. /// "Line feed" control character. const int $lf = 0x0a; diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart new file mode 100644 index 000000000..7f21a8dcd --- /dev/null +++ b/pkgs/package_config/lib/src/util_io.dart @@ -0,0 +1,106 @@ +// Copyright (c) 2020, 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. + +/// Utility methods requiring dart:io and used by more than one library in the +/// package. +library package_config.util_io; + +import 'dart:io'; +import 'dart:typed_data'; + +Future defaultLoader(Uri uri) async { + if (uri.isScheme("file")) { + var file = File.fromUri(uri); + try { + return file.readAsBytes(); + } catch (_) { + return null; + } + } + if (uri.isScheme("http") || uri.isScheme("https")) { + return _httpGet(uri); + } + throw UnsupportedError("Default URI unsupported scheme: $uri"); +} + +Future _httpGet(Uri uri) async { + assert(uri.isScheme("http") || uri.isScheme("https")); + var client = HttpClient(); + var request = await client.getUrl(uri); + var response = await request.close(); + if (response.statusCode != HttpStatus.ok) { + return null; + } + var splitContent = await response.toList(); + var totalLength = 0; + if (splitContent.length == 1) { + var part = splitContent[0]; + if (part is Uint8List) { + return part; + } + } + for (var list in splitContent) { + totalLength += list.length; + } + var result = Uint8List(totalLength); + var offset = 0; + for (Uint8List contentPart in splitContent) { + result.setRange(offset, offset + contentPart.length, contentPart); + offset += contentPart.length; + } + return result; +} + +/// The file name of a path. +/// +/// The file name is everything after the last occurrence of +/// [Platform.pathSeparator], or the entire string if no +/// path separator occurs in the string. +String fileName(String path) { + var separator = Platform.pathSeparator; + var lastSeparator = path.lastIndexOf(separator); + if (lastSeparator < 0) return path; + return path.substring(lastSeparator + separator.length); +} + +/// The directory name of a path. +/// +/// The directory name is everything before the last occurrence of +/// [Platform.pathSeparator], or the empty string if no +/// path separator occurs in the string. +String dirName(String path) { + var separator = Platform.pathSeparator; + var lastSeparator = path.lastIndexOf(separator); + if (lastSeparator < 0) return ""; + return path.substring(0, lastSeparator); +} + +/// Join path parts with the [Platform.pathSeparator]. +/// +/// If a part ends with a path separator, then no extra separator is +/// inserted. +String pathJoin(String part1, String part2, [String part3]) { + var separator = Platform.pathSeparator; + var separator1 = part1.endsWith(separator) ? "" : separator; + if (part3 == null) { + return "$part1$separator1$part2"; + } + var separator2 = part2.endsWith(separator) ? "" : separator; + return "$part1$separator1$part2$separator2$part3"; +} + +/// Join an unknown number of path parts with [Platform.pathSeparator]. +/// +/// If a part ends with a path separator, then no extra separator is +/// inserted. +String pathJoinAll(Iterable parts) { + var buffer = StringBuffer(); + var separator = ""; + for (var part in parts) { + buffer..write(separator)..write(part); + separator = + part.endsWith(Platform.pathSeparator) ? "" : Platform.pathSeparator; + } + return buffer.toString(); +} diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index abaddd9e9..5299fdf79 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.9.0 +version: 1.9.1 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config @@ -14,3 +14,6 @@ dev_dependencies: test: ^1.6.4 matcher: ^0.12.5 pedantic: 1.8.0 + build_runner: ^1.0.0 + build_web_compilers: ^2.0.0 + build_test: ^0.10.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index e4c93a592..1a9a61c1f 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -2,6 +2,7 @@ // 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. +@TestOn('vm') library package_config.discovery_test; import "dart:io"; @@ -9,6 +10,7 @@ import "package:test/test.dart"; import "package:package_config/package_config.dart"; import "src/util.dart"; +import "src/util_io.dart"; const packagesFile = """ # A comment diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 109693c4c..52fca3ffa 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -2,6 +2,7 @@ // 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. +@TestOn('vm') library package_config.discovery_test; import "package:test/test.dart"; diff --git a/pkgs/package_config/test/legacy/discovery_analysis_test.dart b/pkgs/package_config/test/legacy/discovery_analysis_test.dart index 7d08f7b92..4be636d13 100644 --- a/pkgs/package_config/test/legacy/discovery_analysis_test.dart +++ b/pkgs/package_config/test/legacy/discovery_analysis_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @deprecated +@TestOn('vm') library package_config.discovery_analysis_test; import "dart:async"; diff --git a/pkgs/package_config/test/legacy/discovery_test.dart b/pkgs/package_config/test/legacy/discovery_test.dart index 684abcb4a..72874c8df 100644 --- a/pkgs/package_config/test/legacy/discovery_test.dart +++ b/pkgs/package_config/test/legacy/discovery_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @deprecated +@TestOn('vm') library package_config.discovery_test; import "dart:async"; diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 2b91b2130..6e689b734 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -3,65 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:convert'; -import "dart:io"; import 'dart:typed_data'; import "package:test/test.dart"; -import "package:package_config/src/util.dart"; - -/// Creates a directory structure from [description] and runs [fileTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a subdirectory, otherwise it's a file and the value is the content -/// as a string. -/// Introduces a group to hold the [setUp]/[tearDown] logic. -void fileTest(String name, Map description, - void fileTest(Directory directory)) { - group("file-test", () { - var tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); - setUp(() { - _createFiles(tempDir, description); - }); - tearDown(() { - tempDir.deleteSync(recursive: true); - }); - test(name, () => fileTest(tempDir)); - }); -} - -/// Creates a set of files under a new temporary directory. -/// Returns the temporary directory. -/// -/// The [description] is a map from file names to content. -/// If the content is again a map, it represents a subdirectory -/// with the content as description. -/// Otherwise the content should be a string, -/// which is written to the file as UTF-8. -Directory createTestFiles(Map description) { - var target = Directory.systemTemp.createTempSync("pkgcfgtest"); - _createFiles(target, description); - return target; -} - -// Creates temporary files in the target directory. -void _createFiles(Directory target, Map description) { - description.forEach((name, content) { - var entryName = pathJoin(target.path, "$name"); - if (content is Map) { - _createFiles(Directory(entryName)..createSync(), content); - } else { - File(entryName).writeAsStringSync(content, flush: true); - } - }); -} - -/// Creates a [Directory] for a subdirectory of [parent]. -Directory subdir(Directory parent, String dirName) => - Directory(pathJoinAll([parent.path, ...dirName.split("/")])); - -/// Creates a [File] for an entry in the [directory] directory. -File dirFile(Directory directory, String fileName) => - File(pathJoin(directory.path, fileName)); /// Creates a package: URI. Uri pkg(String packageName, String packagePath) { diff --git a/pkgs/package_config/test/src/util_io.dart b/pkgs/package_config/test/src/util_io.dart new file mode 100644 index 000000000..d05618a07 --- /dev/null +++ b/pkgs/package_config/test/src/util_io.dart @@ -0,0 +1,62 @@ +// Copyright (c) 2020, 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. + +import "dart:io"; + +import "package:test/test.dart"; +import "package:package_config/src/util_io.dart"; + +/// Creates a directory structure from [description] and runs [fileTest]. +/// +/// Description is a map, each key is a file entry. If the value is a map, +/// it's a subdirectory, otherwise it's a file and the value is the content +/// as a string. +/// Introduces a group to hold the [setUp]/[tearDown] logic. +void fileTest(String name, Map description, + void fileTest(Directory directory)) { + group("file-test", () { + var tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); + setUp(() { + _createFiles(tempDir, description); + }); + tearDown(() { + tempDir.deleteSync(recursive: true); + }); + test(name, () => fileTest(tempDir)); + }); +} + +/// Creates a set of files under a new temporary directory. +/// Returns the temporary directory. +/// +/// The [description] is a map from file names to content. +/// If the content is again a map, it represents a subdirectory +/// with the content as description. +/// Otherwise the content should be a string, +/// which is written to the file as UTF-8. +Directory createTestFiles(Map description) { + var target = Directory.systemTemp.createTempSync("pkgcfgtest"); + _createFiles(target, description); + return target; +} + +// Creates temporary files in the target directory. +void _createFiles(Directory target, Map description) { + description.forEach((name, content) { + var entryName = pathJoin(target.path, "$name"); + if (content is Map) { + _createFiles(Directory(entryName)..createSync(), content); + } else { + File(entryName).writeAsStringSync(content, flush: true); + } + }); +} + +/// Creates a [Directory] for a subdirectory of [parent]. +Directory subdir(Directory parent, String dirName) => + Directory(pathJoinAll([parent.path, ...dirName.split("/")])); + +/// Creates a [File] for an entry in the [directory] directory. +File dirFile(Directory directory, String fileName) => + File(pathJoin(directory.path, fileName)); From 76d2d33cb621ba722603ac4a7c35a8892a2ad3de Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 14:35:04 -0800 Subject: [PATCH 141/281] Fix reference to pedantic lints (dart-lang/package_config#73) --- pkgs/package_config/analysis_options.yaml | 2 +- pkgs/package_config/pubspec.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml index 82c00e5c8..66639ec1a 100644 --- a/pkgs/package_config/analysis_options.yaml +++ b/pkgs/package_config/analysis_options.yaml @@ -2,7 +2,7 @@ # 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. -include: package:pedantic/analysis_options.yaml +include: package:pedantic/analysis_options.1.9.0.yaml analyzer: errors: annotate_overrides: ignore diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5299fdf79..5c0589145 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -13,7 +13,8 @@ dependencies: dev_dependencies: test: ^1.6.4 matcher: ^0.12.5 - pedantic: 1.8.0 + pedantic: ^1.8.0 + build_runner: ^1.0.0 build_web_compilers: ^2.0.0 build_test: ^0.10.0 From c1b6ac18cc49dc3c924c9798ffec420961987d1c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 15:52:13 -0800 Subject: [PATCH 142/281] Fix version constraint on pkg:pedantic --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5c0589145..853c0514b 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: dev_dependencies: test: ^1.6.4 matcher: ^0.12.5 - pedantic: ^1.8.0 + pedantic: ^1.9.0 build_runner: ^1.0.0 build_web_compilers: ^2.0.0 From c886dde0251b2e78b6824da7ef2f8462c8e578a9 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 12 Mar 2020 12:47:02 +0100 Subject: [PATCH 143/281] Change to only look for package_config.json if asked for .packages by name. (dart-lang/package_config#78) Some clean-up. --- pkgs/package_config/CHANGELOG.md | 5 ++ pkgs/package_config/lib/package_config.dart | 8 ++- .../lib/src/package_config_io.dart | 70 +++++++++---------- .../lib/src/package_config_json.dart | 11 ++- pkgs/package_config/lib/src/util_io.dart | 2 +- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 6 +- .../test/discovery_uri_test.dart | 25 ++++--- 8 files changed, 63 insertions(+), 66 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 1cd45d007..0b5e1563e 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.9.2 + +- Updated to support new rules for picking `package_config.json` over + a specified `.packages`. + ## 1.9.1 - Remove accidental transitive import of `dart:io` from entrypoints that are diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index bca865d70..1113ac872 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -24,9 +24,10 @@ export "package_config_types.dart"; /// It is considered a `package_config.json` file if its first character /// is a `{`. /// -/// If the file is a `.packages` file and [preferNewest] is true, the default, -/// also checks if there is a `.dart_tool/package_config.json` file next to the original file, -/// and if so, loads that instead. +/// If the file is a `.packages` file (the file name is `.packages`) +/// and [preferNewest] is true, the default, also checks if there is +/// a `.dart_tool/package_config.json` file next +/// to the original file, and if so, loads that instead. /// If [preferNewest] is set to false, a directly specified `.packages` file /// is loaded even if there is an available `package_config.json` file. /// The caller can determine this from the [PackageConfig.version] @@ -50,6 +51,7 @@ Future loadPackageConfig(File file, /// non-whitespace character is a `{`. /// /// If [preferNewest] is true, the default, and the file is a `.packages` file, +/// as determined by its file name being `.packages`, /// first checks if there is a `.dart_tool/package_config.json` file /// next to the original file, and if so, loads that instead. /// The [file] *must not* be a `package:` URI. diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index 954be6b1e..31bc1cc99 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -30,6 +30,13 @@ import "util_io.dart"; /// The file must exist and be a normal file. Future readAnyConfigFile( File file, bool preferNewest, void onError(Object error)) async { + if (preferNewest && fileName(file.path) == ".packages") { + var alternateFile = + File(pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); + if (alternateFile.existsSync()) { + return await readPackageConfigJsonFile(alternateFile, onError); + } + } Uint8List bytes; try { bytes = await file.readAsBytes(); @@ -37,28 +44,7 @@ Future readAnyConfigFile( onError(e); return const SimplePackageConfig.empty(); } - var firstChar = firstNonWhitespaceChar(bytes); - if (firstChar != $lbrace) { - // Definitely not a JSON object, probably a .packages. - if (preferNewest) { - var alternateFile = File( - pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); - if (alternateFile.existsSync()) { - Uint8List /*?*/ bytes; - try { - bytes = await alternateFile.readAsBytes(); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - if (bytes != null) { - return parsePackageConfigBytes(bytes, alternateFile.uri, onError); - } - } - } - return packages_file.parse(bytes, file.uri, onError); - } - return parsePackageConfigBytes(bytes, file.uri, onError); + return parseAnyConfigFile(bytes, file.uri, onError); } /// Like [readAnyConfigFile] but uses a URI and an optional loader. @@ -73,11 +59,24 @@ Future readAnyConfigFileUri( } if (loader == null) { if (file.isScheme("file")) { - return readAnyConfigFile(File.fromUri(file), preferNewest, onError); + return await readAnyConfigFile(File.fromUri(file), preferNewest, onError); } loader = defaultLoader; } - Uint8List bytes; + if (preferNewest && file.pathSegments.last == ".packages") { + var alternateFile = file.resolve(".dart_tool/package_config.json"); + Uint8List /*?*/ bytes; + try { + bytes = await loader(alternateFile); + } catch (e) { + onError(e); + return const SimplePackageConfig.empty(); + } + if (bytes != null) { + return parsePackageConfigBytes(bytes, alternateFile, onError); + } + } + Uint8List /*?*/ bytes; try { bytes = await loader(file); } catch (e) { @@ -89,23 +88,18 @@ Future readAnyConfigFileUri( file.toString(), "file", "File cannot be read")); return const SimplePackageConfig.empty(); } + return parseAnyConfigFile(bytes, file, onError); +} + +/// Parses a `.packages` or `package_config.json` file's contents. +/// +/// Assumes it's a JSON file if the first non-whitespace character +/// is `{`, otherwise assumes it's a `.packages` file. +PackageConfig parseAnyConfigFile( + Uint8List bytes, Uri file, void onError(Object error)) { var firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { // Definitely not a JSON object, probably a .packages. - if (preferNewest) { - // Check if there is a package_config.json file. - var alternateFile = file.resolveUri(packageConfigJsonPath); - Uint8List alternateBytes; - try { - alternateBytes = await loader(alternateFile); - } catch (e) { - onError(e); - return const SimplePackageConfig.empty(); - } - if (alternateBytes != null) { - return parsePackageConfigBytes(alternateBytes, alternateFile, onError); - } - } return packages_file.parse(bytes, file, onError); } return parsePackageConfigBytes(bytes, file, onError); diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index b9b34165b..27abf505c 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -39,7 +39,7 @@ PackageConfig parsePackageConfigBytes( try { jsonObject = _jsonUtf8Decoder.convert(bytes); } on FormatException catch (e) { - onError(PackageConfigFormatException(e.message, e.source, e.offset)); + onError(PackageConfigFormatException.from(e)); return const SimplePackageConfig.empty(); } return parsePackageConfigJson(jsonObject, file, onError); @@ -51,7 +51,7 @@ PackageConfig parsePackageConfigString( try { jsonObject = jsonDecode(source); } on FormatException catch (e) { - onError(PackageConfigFormatException(e.message, e.source, e.offset)); + onError(PackageConfigFormatException.from(e)); return const SimplePackageConfig.empty(); } return parsePackageConfigJson(jsonObject, file, onError); @@ -271,7 +271,6 @@ void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) { } } packages_file.write(output, config, baseUri: baseUri, comment: comment); - return; } /// If "extraData" is a JSON map, then return it, otherwise return null. @@ -304,12 +303,10 @@ bool _validateJson(dynamic object) { if (object == null || true == object || false == object) return true; if (object is num || object is String) return true; if (object is List) { - for (var element in object) if (!_validateJson(element)) return false; - return true; + return object.every(_validateJson); } if (object is Map) { - for (var value in object.values) if (!_validateJson(value)) return false; - return true; + return object.values.every(_validateJson); } return false; } diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart index 7f21a8dcd..2aa8c94bf 100644 --- a/pkgs/package_config/lib/src/util_io.dart +++ b/pkgs/package_config/lib/src/util_io.dart @@ -13,7 +13,7 @@ Future defaultLoader(Uri uri) async { if (uri.isScheme("file")) { var file = File.fromUri(uri); try { - return file.readAsBytes(); + return await file.readAsBytes(); } catch (_) { return null; } diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 853c0514b..3f5ec27e0 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.9.1 +version: 1.9.2 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 1a9a61c1f..5cbc99214 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -301,13 +301,13 @@ void main() { }); // Find package_config.json in subdir even if initial file syntax error. - fileTest("specified file syntax error", { - "anyname": "syntax error", + fileTest("specified file syntax onError", { + ".packages": "syntax error", ".dart_tool": { "package_config.json": packageConfigFile, }, }, (Directory directory) async { - var file = dirFile(directory, "anyname"); + var file = dirFile(directory, ".packages"); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 52fca3ffa..23c02d7bc 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -60,7 +60,7 @@ void main() { ".dart_tool": { "package_config.json": packageConfigFile, } - }, (Uri directory, loader) async { + }, (directory, loader) async { var config = await findPackageConfigUri(directory, loader: loader); expect(config.version, 2); // Found package_config.json file. validatePackagesFile(config, directory); @@ -71,7 +71,7 @@ void main() { ".packages": packagesFile, "script.dart": "main(){}", "packages": {"shouldNotBeFound": {}} - }, (Uri directory, loader) async { + }, (directory, loader) async { var config = await findPackageConfigUri(directory, loader: loader); expect(config.version, 1); // Found .packages file. validatePackagesFile(config, directory); @@ -86,7 +86,7 @@ void main() { "subdir": { "script.dart": "main(){}", } - }, (Uri directory, loader) async { + }, (directory, loader) async { var config = await findPackageConfigUri(directory.resolve("subdir/"), loader: loader); expect(config.version, 2); @@ -97,7 +97,7 @@ void main() { loaderTest(".packages recursive", { ".packages": packagesFile, "subdir": {"script.dart": "main(){}"} - }, (Uri directory, loader) async { + }, (directory, loader) async { var config; config = await findPackageConfigUri(directory.resolve("subdir/"), loader: loader); @@ -240,9 +240,9 @@ void main() { throwsFormatException); }); - loaderTest("specified file syntax error", { + loaderTest("specified file syntax onError", { "anyname": "syntax error", - }, (Uri directory, loader) async { + }, (directory, loader) async { var file = directory.resolve("anyname"); var hadError = false; await loadPackageConfigUri(file, @@ -254,23 +254,22 @@ void main() { expect(hadError, true); }); - // Find package_config.json in subdir even if initial file syntax error. - loaderTest("specified file syntax error", { + // Don't look for package_config.json if original file not named .packages. + loaderTest("specified file syntax error with alternative", { "anyname": "syntax error", ".dart_tool": { "package_config.json": packageConfigFile, }, - }, (Uri directory, loader) async { + }, (directory, loader) async { var file = directory.resolve("anyname"); - var config = await loadPackageConfigUri(file, loader: loader); - expect(config.version, 2); - validatePackagesFile(config, directory); + expect(() => loadPackageConfigUri(file, loader: loader), + throwsFormatException); }); // A file starting with `{` is a package_config.json file. loaderTest("file syntax error with {", { ".packages": "{syntax error", - }, (Uri directory, loader) async { + }, (directory, loader) async { var file = directory.resolve(".packages"); var hadError = false; await loadPackageConfigUri(file, From 718abb92e6e94c669621bc8d87f1301302c82d4d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 15 Mar 2020 12:47:23 -0700 Subject: [PATCH 144/281] Remove author from the pubspec --- pkgs/pool/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index ebb05d9a2..c87617f43 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -4,7 +4,6 @@ version: 1.4.1-dev description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. -author: Dart Team homepage: https://github.com/dart-lang/pool environment: From 9caf0c1923cef73305a371b5fafedb543ef56c22 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 18 Mar 2020 15:23:02 +0100 Subject: [PATCH 145/281] Make `.packages` files be more clever about defaults. (dart-lang/package_config#80) * Make `.packages` files be more clever about defaults. The `PackageConfig` for a `.packages` file now assigns a default language version of 2.7 to all packages, and if the package location ends in `/lib/`, it assumes the package's root directory is the parent directory of that. * Fix test. * Fix another test. --- pkgs/package_config/CHANGELOG.md | 2 ++ .../package_config/lib/src/packages_file.dart | 21 +++++++++++++++---- pkgs/package_config/test/parse_test.dart | 4 ++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 0b5e1563e..3015523c2 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -2,6 +2,8 @@ - Updated to support new rules for picking `package_config.json` over a specified `.packages`. +- Deduce package root from `.packages` derived package configuration, + and default all such packages to language version 2.7. ## 1.9.1 diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index e65e7e8a6..184b0dd04 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -7,6 +7,12 @@ import "package_config_impl.dart"; import "util.dart"; import "errors.dart"; +/// The language version prior to the release of language versioning. +/// +/// This is the default language version used by all packages from a +/// `.packages` file. +final LanguageVersion _languageVersion = LanguageVersion(2, 7); + /// Parses a `.packages` file into a [PackageConfig]. /// /// The [source] is the byte content of a `.packages` file, assumed to be @@ -100,17 +106,24 @@ PackageConfig parse( "Package URI as location for package", source, separatorIndex + 1)); continue; } - if (!packageLocation.path.endsWith('/')) { - packageLocation = - packageLocation.replace(path: packageLocation.path + "/"); + var path = packageLocation.path; + if (!path.endsWith('/')) { + path += "/"; + packageLocation = packageLocation.replace(path: path); } if (packageNames.contains(packageName)) { onError(PackageConfigFormatException( "Same package name occured more than once", source, start)); continue; } + var rootUri = packageLocation; + if (path.endsWith("/lib/")) { + // Assume default Pub package layout. Include package itself in root. + rootUri = + packageLocation.replace(path: path.substring(0, path.length - 4)); + } var package = SimplePackage.validate( - packageName, packageLocation, packageLocation, null, null, (error) { + packageName, rootUri, packageLocation, _languageVersion, null, (error) { if (error is ArgumentError) { onError(PackageConfigFormatException(error.message, source)); } else { diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 367b64384..59a7e7126 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -34,9 +34,9 @@ void main() { var foo = result["foo"]; expect(foo, isNotNull); - expect(foo.root, Uri.parse("file:///foo/lib/")); + expect(foo.root, Uri.parse("file:///foo/")); expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); - expect(foo.languageVersion, null); + expect(foo.languageVersion, LanguageVersion(2, 7)); }); test("valid empty", () { From 19182255aaa1a5b1869606264c20bafcccee25a3 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 26 Mar 2020 17:09:12 +0100 Subject: [PATCH 146/281] Fix Package constructor not accepting relative packageUriRoot. (dart-lang/package_config#82) * Fix Package constructor not accepting relative packageUriRoot. --- pkgs/package_config/CHANGELOG.md | 4 + .../lib/src/package_config.dart | 2 +- .../lib/src/package_config_impl.dart | 5 +- pkgs/package_config/pubspec.yaml | 2 +- .../test/package_config_impl_test.dart | 145 ++++++++++++++++++ 5 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 pkgs/package_config/test/package_config_impl_test.dart diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 3015523c2..6dcae80cf 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.3 + +- Fix `Package` constructor not accepting relative `packageUriRoot`. + ## 1.9.2 - Updated to support new rules for picking `package_config.json` over diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 364df75b1..30c758a96 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -219,7 +219,7 @@ abstract class Package { /// The [packageUriRoot], if provided, must be either an absolute /// directory URI or a relative URI reference which is then resolved /// relative to [root]. It must then also be a subdirectory of [root], - /// or the same directory. + /// or the same directory, and must end with `/`. /// If [languageVersion] is supplied, it must be a valid Dart language /// version, which means two decimal integer literals separated by a `.`, /// where the integer literals have no leading zeros unless they are diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index f68a9ea75..9e23af063 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -214,7 +214,10 @@ class SimplePackage implements Package { root = root.replace(path: root.path + "/"); } } - if (!fatalError) { + if (packageUriRoot == null) { + packageUriRoot = root; + } else if (!fatalError) { + packageUriRoot = root.resolveUri(packageUriRoot); if (!isAbsoluteDirectoryUri(packageUriRoot)) { onError(PackageConfigArgumentError( packageUriRoot, diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 3f5ec27e0..b7d596910 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 1.9.2 +version: 1.9.3 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart new file mode 100644 index 000000000..6921118f3 --- /dev/null +++ b/pkgs/package_config/test/package_config_impl_test.dart @@ -0,0 +1,145 @@ +// Copyright (c) 2020, 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. + +import "package:package_config/package_config_types.dart"; +import "package:test/test.dart"; +import "src/util.dart"; + +void main() { + var unique = Object(); + var root = Uri.file("/tmp/root/"); + + group("LanguageVersion", () { + test("minimal", () { + var version = LanguageVersion(3, 5); + expect(version.major, 3); + expect(version.minor, 5); + }); + + test("negative major", () { + expect(() => LanguageVersion(-1, 1), throwsArgumentError); + }); + + test("negative minor", () { + expect(() => LanguageVersion(1, -1), throwsArgumentError); + }); + + test("minimal parse", () { + var version = LanguageVersion.parse("3.5"); + expect(version.major, 3); + expect(version.minor, 5); + }); + + void failParse(String name, String input) { + test("$name - error", () { + expect(() => LanguageVersion.parse(input), + throwsA(TypeMatcher())); + expect(() => LanguageVersion.parse(input), throwsFormatException); + var failed = false; + var actual = LanguageVersion.parse(input, onError: (_) { + failed = true; + }); + expect(failed, true); + expect(actual, isA()); + }); + } + + failParse("Leading zero major", "01.1"); + failParse("Leading zero minor", "1.01"); + failParse("Sign+ major", "+1.1"); + failParse("Sign- major", "-1.1"); + failParse("Sign+ minor", "1.+1"); + failParse("Sign- minor", "1.-1"); + failParse("WhiteSpace 1", " 1.1"); + failParse("WhiteSpace 2", "1 .1"); + failParse("WhiteSpace 3", "1. 1"); + failParse("WhiteSpace 4", "1.1 "); + }); + + group("Package", () { + test("minimal", () { + var package = Package("name", root, extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, root); + expect(package.languageVersion, null); + expect(package.extraData, same(unique)); + }); + + test("absolute package root", () { + var version = LanguageVersion(1, 1); + var absolute = root.resolve("foo/bar/"); + var package = Package("name", root, + packageUriRoot: absolute, + languageVersion: version, + extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, absolute); + expect(package.languageVersion, version); + expect(package.extraData, same(unique)); + }); + + test("relative package root", () { + var relative = Uri.parse("foo/bar/"); + var absolute = root.resolveUri(relative); + var package = + Package("name", root, packageUriRoot: relative, extraData: unique); + expect(package.name, "name"); + expect(package.root, root); + expect(package.packageUriRoot, absolute); + expect(package.languageVersion, null); + expect(package.extraData, same(unique)); + }); + + for (var badName in ["a/z", "a:z", "", "..."]) { + test("Invalid name '$badName'", () { + expect(() => Package(badName, root), throwsPackageConfigError); + }); + } + + test("Invalid root, not absolute", () { + expect( + () => Package("name", Uri.parse("/foo/")), throwsPackageConfigError); + }); + + test("Invalid root, not ending in slash", () { + expect(() => Package("name", Uri.parse("file:///foo")), + throwsPackageConfigError); + }); + + test("invalid package root, not ending in slash", () { + expect(() => Package("name", root, packageUriRoot: Uri.parse("foo")), + throwsPackageConfigError); + }); + + test("invalid package root, not inside root", () { + expect(() => Package("name", root, packageUriRoot: Uri.parse("../baz/")), + throwsPackageConfigError); + }); + }); + + group("package config", () { + test("emtpy", () { + var empty = PackageConfig([], extraData: unique); + expect(empty.version, 2); + expect(empty.packages, isEmpty); + expect(empty.extraData, same(unique)); + expect(empty.resolve(pkg("a", "b")), isNull); + }); + + test("single", () { + var package = Package("name", root); + var single = PackageConfig([package], extraData: unique); + expect(single.version, 2); + expect(single.packages, hasLength(1)); + expect(single.extraData, same(unique)); + expect(single.resolve(pkg("a", "b")), isNull); + var resolved = single.resolve(pkg("name", "a/b")); + expect(resolved, root.resolve("a/b")); + }); + }); +} + +final Matcher throwsPackageConfigError = throwsA(isA()); From 5f06761b02746ce88a5f269b1b09a146a9e6e0a3 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 6 May 2020 14:59:21 -0700 Subject: [PATCH 147/281] fix a lint about an unused import --- pkgs/package_config/.travis.yml | 2 +- pkgs/package_config/lib/src/package_config_io.dart | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index 09fc296c2..3a47bb586 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -5,7 +5,7 @@ dart: dart_task: - test - dartfmt - - dartanalyzer: --fatal-warnings . + - dartanalyzer: --fatal-warnings --fatal-infos . matrix: include: diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index 31bc1cc99..bfbb1e373 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -8,7 +8,6 @@ import "dart:convert"; import "dart:io"; import "dart:typed_data"; -import "discovery.dart" show packageConfigJsonPath; import "errors.dart"; import "package_config_impl.dart"; import "package_config_json.dart"; From b4d7bdc3f47d2b59b30f394729f43ef2096cdd59 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jun 2020 11:52:21 -0700 Subject: [PATCH 148/281] Remove deprecated lint --- pkgs/pool/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index f8eebb47a..2c837ba4d 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -62,7 +62,6 @@ linter: - prefer_typing_uninitialized_variables - recursive_getters - slash_for_doc_comments - - super_goes_last - test_types_in_equals - throw_in_finally - type_init_formals From c26f921bdb85466ee6522dce983732a530d1630e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jun 2020 11:53:39 -0700 Subject: [PATCH 149/281] Remove lints duplicated in pkg:pedantic --- pkgs/pool/analysis_options.yaml | 39 ++------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 2c837ba4d..8bef8818d 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -1,22 +1,15 @@ include: package:pedantic/analysis_options.yaml + analyzer: strong-mode: implicit-casts: false + linter: rules: - - always_declare_return_types - - annotate_overrides - - avoid_empty_else - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - avoid_renaming_method_parameters - - avoid_return_types_on_setters - avoid_returning_null - avoid_returning_null_for_future - - avoid_shadowing_type_parameters - - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - await_only_futures - camel_case_types @@ -25,58 +18,30 @@ linter: - constant_identifier_names - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - empty_statements - hash_and_equals - implementation_imports - invariant_booleans - iterable_contains_unrelated_type - - library_names - - library_prefixes - list_remove_unrelated_type - literal_only_boolean_expressions - no_adjacent_strings_in_list - - no_duplicate_case_values - non_constant_identifier_names - - null_closures - - omit_local_variable_types - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - #- prefer_final_locals - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - #- prefer_single_quotes - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - - unawaited_futures - unnecessary_await_in_return - unnecessary_brace_in_string_interps - - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_function_type_syntax_for_parameters - - use_rethrow_when_possible - - valid_regexps From 453166966c10ef615724ea2c6ea0fff9e8fe4448 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jun 2020 11:54:52 -0700 Subject: [PATCH 150/281] CI: test on the oldest supported SDK Also use Chrome instead of firefox for browser testing --- pkgs/pool/.travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index 07e132f33..18f741339 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -1,11 +1,11 @@ language: dart dart: + - 2.0.0 - dev dart_task: - - test: --platform vm - - test: --platform firefox + - test: --platform vm,chrome - dartfmt - dartanalyzer: --fatal-infos --fatal-warnings . From 697988daa5dcd6241c14278579b5db775e66ba4c Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 15 Jul 2020 08:40:16 -0700 Subject: [PATCH 151/281] Merge the null_safety branch into master (dart-lang/pool#40) --- pkgs/pool/.travis.yml | 39 +++++++-- pkgs/pool/CHANGELOG.md | 3 +- pkgs/pool/analysis_options.yaml | 5 ++ pkgs/pool/benchmark/for_each_benchmark.dart | 10 +-- pkgs/pool/lib/pool.dart | 59 +++++++------ pkgs/pool/pubspec.yaml | 91 ++++++++++++++++++++- pkgs/pool/test/pool_test.dart | 17 ++-- 7 files changed, 166 insertions(+), 58 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index 18f741339..906158956 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -1,18 +1,39 @@ language: dart dart: - - 2.0.0 - - dev + - dev -dart_task: - - test: --platform vm,chrome - - dartfmt - - dartanalyzer: --fatal-infos --fatal-warnings . +jobs: + include: + - stage: analyze_and_format + name: "Analyze" + dart: dev + os: linux + script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + - stage: analyze_and_format + name: "Format" + dart: dev + os: linux + script: dartfmt -n --set-exit-if-changed . + - stage: test + name: "Vm Tests" + dart: dev + os: linux + script: pub run --enable-experiment=non-nullable test -p vm + - stage: test + name: "Web Tests" + dart: dev + os: linux + script: pub run --enable-experiment=non-nullable test -p chrome + +stages: + - analyze_and_format + - test # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: - directories: - - $HOME/.pub-cache + directories: + - $HOME/.pub-cache diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index c680dd2bf..a413d7880 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,5 +1,6 @@ -## 1.4.1 +## 1.5.0-nullsafety +* Migrate to null safety. * `forEach`: Avoid `await null` if the `Stream` is not paused. Improves trivial benchmark by 40%. diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 8bef8818d..986bccc6c 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -4,6 +4,9 @@ analyzer: strong-mode: implicit-casts: false + enable-experiment: + - non-nullable + linter: rules: - avoid_function_literals_in_foreach_calls @@ -36,6 +39,8 @@ linter: - prefer_initializing_formals - prefer_interpolation_to_compose_strings - prefer_typing_uninitialized_variables + - recursive_getters + - slash_for_doc_comments - test_types_in_equals - throw_in_finally - unnecessary_await_in_return diff --git a/pkgs/pool/benchmark/for_each_benchmark.dart b/pkgs/pool/benchmark/for_each_benchmark.dart index 7438ace78..2973b2a36 100644 --- a/pkgs/pool/benchmark/for_each_benchmark.dart +++ b/pkgs/pool/benchmark/for_each_benchmark.dart @@ -8,22 +8,22 @@ void main(List args) async { final watch = Stopwatch()..start(); final start = DateTime.now(); - DateTime lastLog; - Duration fastest; - int fastestIteration; + DateTime? lastLog; + Duration? fastest; + late int fastestIteration; var i = 1; void log(bool force) { var now = DateTime.now(); if (force || lastLog == null || - now.difference(lastLog) > const Duration(seconds: 1)) { + now.difference(lastLog!) > const Duration(seconds: 1)) { lastLog = now; print([ now.difference(start), i.toString().padLeft(10), fastestIteration.toString().padLeft(7), - fastest.inMicroseconds.toString().padLeft(9) + fastest!.inMicroseconds.toString().padLeft(9) ].join(' ')); } } diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index d8565411a..20ab8f181 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -51,16 +51,16 @@ class Pool { /// for additional files to be read before they could be closed. /// /// This is `null` if this pool shouldn't time out. - RestartableTimer _timer; + RestartableTimer? _timer; /// The amount of time to wait before timing out the pending resources. - final Duration _timeout; + final Duration? _timeout; /// A [FutureGroup] that tracks all the `onRelease` callbacks for resources /// that have been marked releasable. /// /// This is `null` until [close] is called. - FutureGroup _closeGroup; + FutureGroup? _closeGroup; /// Whether [close] has been called. bool get isClosed => _closeMemo.hasRun; @@ -78,7 +78,7 @@ class Pool { /// If [timeout] is passed, then if that much time passes without any activity /// all pending [request] futures will throw a [TimeoutException]. This is /// intended to avoid deadlocks. - Pool(this._maxAllocatedResources, {Duration timeout}) : _timeout = timeout { + Pool(this._maxAllocatedResources, {Duration? timeout}) : _timeout = timeout { if (_maxAllocatedResources <= 0) { throw ArgumentError.value(_maxAllocatedResources, 'maxAllocatedResources', 'Must be greater than zero.'); @@ -152,17 +152,17 @@ class Pool { /// to, a [StateError] is thrown. Stream forEach( Iterable elements, FutureOr Function(S source) action, - {bool Function(S item, Object error, StackTrace stack) onError}) { + {bool Function(S item, Object error, StackTrace stack)? onError}) { onError ??= (item, e, s) => true; var cancelPending = false; - Completer resumeCompleter; - StreamController controller; + Completer? resumeCompleter; + late StreamController controller; - Iterator iterator; + late Iterator iterator; - Future run(int i) async { + Future run(int _) async { while (iterator.moveNext()) { // caching `current` is necessary because there are async breaks // in this code and `iterator` is shared across many workers @@ -171,7 +171,7 @@ class Pool { _resetTimer(); if (resumeCompleter != null) { - await resumeCompleter.future; + await resumeCompleter!.future; } if (cancelPending) { @@ -182,7 +182,7 @@ class Pool { try { value = await action(current); } catch (e, stack) { - if (onError(current, e, stack)) { + if (onError!(current, e, stack)) { controller.addError(e, stack); } continue; @@ -191,20 +191,19 @@ class Pool { } } - Future doneFuture; + Future? doneFuture; void onListen() { - assert(iterator == null); iterator = elements.iterator; assert(doneFuture == null); - doneFuture = Future.wait( - Iterable.generate(_maxAllocatedResources) - .map((i) => withResource(() => run(i))), - eagerError: true) + var futures = Iterable>.generate( + _maxAllocatedResources, (i) => withResource(() => run(i))); + doneFuture = Future.wait(futures, eagerError: true) + .then((_) {}) .catchError(controller.addError); - doneFuture.whenComplete(controller.close); + doneFuture!.whenComplete(controller.close); } controller = StreamController( @@ -217,11 +216,11 @@ class Pool { }, onPause: () { assert(resumeCompleter == null); - resumeCompleter = Completer(); + resumeCompleter = Completer(); }, onResume: () { assert(resumeCompleter != null); - resumeCompleter.complete(); + resumeCompleter!.complete(); resumeCompleter = null; }, ); @@ -241,20 +240,20 @@ class Pool { /// /// This may be called more than once; it returns the same [Future] each time. Future close() => _closeMemo.runOnce(() { - if (_closeGroup != null) return _closeGroup.future; + if (_closeGroup != null) return _closeGroup!.future; _resetTimer(); _closeGroup = FutureGroup(); for (var callback in _onReleaseCallbacks) { - _closeGroup.add(Future.sync(callback)); + _closeGroup!.add(Future.sync(callback)); } _allocatedResources -= _onReleaseCallbacks.length; _onReleaseCallbacks.clear(); - if (_allocatedResources == 0) _closeGroup.close(); - return _closeGroup.future; + if (_allocatedResources == 0) _closeGroup!.close(); + return _closeGroup!.future; }); final _closeMemo = AsyncMemoizer(); @@ -267,7 +266,7 @@ class Pool { pending.complete(PoolResource._(this)); } else { _allocatedResources--; - if (isClosed && _allocatedResources == 0) _closeGroup.close(); + if (isClosed && _allocatedResources == 0) _closeGroup!.close(); } } @@ -280,9 +279,9 @@ class Pool { var pending = _requestedResources.removeFirst(); pending.complete(_runOnRelease(onRelease)); } else if (isClosed) { - _closeGroup.add(Future.sync(onRelease)); + _closeGroup!.add(Future.sync(onRelease)); _allocatedResources--; - if (_allocatedResources == 0) _closeGroup.close(); + if (_allocatedResources == 0) _closeGroup!.close(); } else { var zone = Zone.current; var registered = zone.registerCallback(onRelease); @@ -298,7 +297,7 @@ class Pool { Future _runOnRelease(Function() onRelease) { Future.sync(onRelease).then((value) { _onReleaseCompleters.removeFirst().complete(PoolResource._(this)); - }).catchError((error, StackTrace stackTrace) { + }).catchError((Object error, StackTrace stackTrace) { _onReleaseCompleters.removeFirst().completeError(error, stackTrace); }); @@ -312,9 +311,9 @@ class Pool { if (_timer == null) return; if (_requestedResources.isEmpty) { - _timer.cancel(); + _timer!.cancel(); } else { - _timer.reset(); + _timer!.reset(); } } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index c87617f43..8fc0e1435 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.4.1-dev +version: 1.5.0-nullsafety description: >- Manage a finite pool of resources. @@ -7,13 +7,96 @@ description: >- homepage: https://github.com/dart-lang/pool environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dependencies: - async: '>=1.4.0 <3.0.0' - stack_trace: '>=0.9.2 <2.0.0' + async: '>=2.5.0-nullsafety <2.5.0' + stack_trace: '>=1.10.0-nullsafety <1.10.0' dev_dependencies: fake_async: ^1.0.0 pedantic: ^1.4.0 test: ^1.0.0 + +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + clock: + git: + url: git://github.com/dart-lang/clock.git + ref: null_safety + collection: 1.15.0-nullsafety + js: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/js + fake_async: + git: + url: git://github.com/dart-lang/fake_async.git + ref: null_safety + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: 1.3.0-nullsafety + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + source_maps: + git: + url: git://github.com/dart-lang/source_maps.git + ref: null_safety + source_map_stack_trace: + git: + url: git://github.com/dart-lang/source_map_stack_trace.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stack_trace: + git: + url: git://github.com/dart-lang/stack_trace.git + ref: null_safety + stream_channel: + git: + url: git://github.com/dart-lang/stream_channel.git + ref: null_safety + string_scanner: + git: + url: git://github.com/dart-lang/string_scanner.git + ref: null_safety + term_glyph: + git: + url: git://github.com/dart-lang/term_glyph.git + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_core + test: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 091cd5513..20e92d597 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -438,7 +438,7 @@ void main() { }); group('forEach', () { - Pool pool; + late Pool pool; tearDown(() async { await pool.close(); @@ -609,7 +609,7 @@ void main() { delayedToString); // ignore: cancel_subscriptions - StreamSubscription subscription; + late StreamSubscription subscription; subscription = stream.listen( (data) { @@ -659,9 +659,9 @@ void main() { }); group('errors', () { - Future errorInIterator( - {bool Function(int item, Object error, StackTrace stack) - onError}) async { + Future errorInIterator({ + bool Function(int item, Object error, StackTrace stack)? onError, + }) async { pool = Pool(20); var listFuture = pool @@ -704,7 +704,8 @@ void main() { test('error in action, no onError', () async { pool = Pool(20); - var list = await pool.forEach(Iterable.generate(100), (i) async { + var list = await pool.forEach(Iterable.generate(100), + (int i) async { await Future.delayed(const Duration(milliseconds: 10)); if (i % 10 == 0) { throw UnsupportedError('Multiples of 10 not supported'); @@ -737,9 +738,7 @@ void Function() expectNoAsync() { /// A matcher for Futures that asserts that they don't complete. /// /// This should only be called within a [FakeAsync.run] zone. -Matcher get doesNotComplete => predicate((future) { - expect(future, const TypeMatcher()); - +Matcher get doesNotComplete => predicate((Future future) { var stack = Trace.current(1); future.then((_) => registerException( TestFailure('Expected future not to complete.'), stack)); From e1c70134378a3c472c17912b43956bf4b3b75067 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:01 -0700 Subject: [PATCH 152/281] update for the 2.10 dev sdk (dart-lang/pool#41) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/pool/.travis.yml | 12 +++---- pkgs/pool/pubspec.yaml | 76 +++++++++++++----------------------------- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index 906158956..f0d3128a3 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -1,28 +1,28 @@ language: dart dart: - - dev + - preview/raw/2.10.0-0.2-dev jobs: include: - stage: analyze_and_format name: "Analyze" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p vm - stage: test name: "Web Tests" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p chrome @@ -32,7 +32,7 @@ stages: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 8fc0e1435..ea3cd611f 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -7,7 +7,8 @@ description: >- homepage: https://github.com/dart-lang/pool environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' @@ -20,83 +21,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: - git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety - clock: - git: - url: git://github.com/dart-lang/clock.git - ref: null_safety - collection: 1.15.0-nullsafety + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git js: git: url: git://github.com/dart-lang/sdk.git path: pkg/js - fake_async: - git: - url: git://github.com/dart-lang/fake_async.git - ref: null_safety + ref: 2-10-pkgs matcher: + git: git://github.com/dart-lang/matcher.git + meta: git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety - meta: 1.3.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git source_maps: - git: - url: git://github.com/dart-lang/source_maps.git - ref: null_safety + git: git://github.com/dart-lang/source_maps.git source_map_stack_trace: - git: - url: git://github.com/dart-lang/source_map_stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stack_trace: - git: - url: git://github.com/dart-lang/stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/stack_trace.git stream_channel: - git: - url: git://github.com/dart-lang/stream_channel.git - ref: null_safety + git: git://github.com/dart-lang/stream_channel.git string_scanner: - git: - url: git://github.com/dart-lang/string_scanner.git - ref: null_safety + git: git://github.com/dart-lang/string_scanner.git term_glyph: - git: - url: git://github.com/dart-lang/term_glyph.git - ref: null_safety + git: git://github.com/dart-lang/term_glyph.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_core test: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From 71dd2a95aae6c878c54e66bf97a4f8edd9bd8d24 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 22 Jul 2020 14:26:52 -0700 Subject: [PATCH 153/281] Fixes for Dart 2.10 (dart-lang/pool#42) --- pkgs/pool/.travis.yml | 6 +----- pkgs/pool/pubspec.yaml | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index f0d3128a3..87be92616 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -1,28 +1,24 @@ language: dart dart: - - preview/raw/2.10.0-0.2-dev + - dev jobs: include: - stage: analyze_and_format name: "Analyze" - dart: preview/raw/2.10.0-0.2-dev os: linux script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p vm - stage: test name: "Web Tests" - dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p chrome diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index ea3cd611f..abc21b5b1 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -28,6 +28,10 @@ dependency_overrides: git: git://github.com/dart-lang/charcode.git collection: git: git://github.com/dart-lang/collection.git + clock: + git: git://github.com/dart-lang/clock.git + fake_async: + git: git://github.com/dart-lang/fake_async.git js: git: url: git://github.com/dart-lang/sdk.git From 9e73f83d7adc99944318d39f22ec323c1e2f468c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:03:58 -0700 Subject: [PATCH 154/281] Prepare for the 2.11 dev SDKs (dart-lang/pool#43) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index a413d7880..5d9f6c479 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.0-nullsafety.1 + +* Allow 2.10 stable and 2.11.0 dev SDK versions. + ## 1.5.0-nullsafety * Migrate to null safety. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index abc21b5b1..68b7bb117 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.0-nullsafety +version: 1.5.0-nullsafety.1 description: >- Manage a finite pool of resources. @@ -8,7 +8,7 @@ homepage: https://github.com/dart-lang/pool environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' From 8897a35cdd881ebf735193c80642c67f7152a697 Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Mon, 28 Sep 2020 02:54:40 -0700 Subject: [PATCH 155/281] Remove unused async imports (dart-lang/package_config#91) Since this version doesn't support Dart pre 2.0, these imports are unnecessary. --- pkgs/package_config/lib/discovery.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart index a2f53c0e6..a72bb1255 100644 --- a/pkgs/package_config/lib/discovery.dart +++ b/pkgs/package_config/lib/discovery.dart @@ -5,7 +5,6 @@ @Deprecated("Use the package_config.json based API") library package_config.discovery; -import "dart:async"; import "dart:io"; import "dart:typed_data" show Uint8List; From c5aa0eae0fca95113b2e0dd73c76dccb139fabb5 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:06:17 -0700 Subject: [PATCH 156/281] allow the 2.12 prerelease sdks (dart-lang/pool#44) --- pkgs/pool/CHANGELOG.md | 4 +++ pkgs/pool/pubspec.yaml | 68 ++++-------------------------------------- 2 files changed, 9 insertions(+), 63 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 5d9f6c479..035605e5a 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.0-nullsafety.2 + +* Allow prerelease versions of the 2.12 sdk. + ## 1.5.0-nullsafety.1 * Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 68b7bb117..5e0a69b7b 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.0-nullsafety.1 +version: 1.5.0-nullsafety.2 description: >- Manage a finite pool of resources. @@ -8,71 +8,13 @@ homepage: https://github.com/dart-lang/pool environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.10.0-0 <2.12.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' stack_trace: '>=1.10.0-nullsafety <1.10.0' dev_dependencies: - fake_async: ^1.0.0 - pedantic: ^1.4.0 - test: ^1.0.0 - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - clock: - git: git://github.com/dart-lang/clock.git - fake_async: - git: git://github.com/dart-lang/fake_async.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - stream_channel: - git: git://github.com/dart-lang/stream_channel.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + fake_async: ^1.2.0-nullsafety + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety From 0d507156dcefd29c766791c26ad8d4e2f6e76ff0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 14:23:08 -0800 Subject: [PATCH 157/281] Bump SDK constraints for pub (dart-lang/pool#45) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/pool/CHANGELOG.md | 5 +++++ pkgs/pool/pubspec.yaml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 035605e5a..6fd755bbb 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.5.0-nullsafety.3 + +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. + ## 1.5.0-nullsafety.2 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 5e0a69b7b..67d8b6c7a 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.0-nullsafety.2 +version: 1.5.0-nullsafety.3 description: >- Manage a finite pool of resources. @@ -7,8 +7,7 @@ description: >- homepage: https://github.com/dart-lang/pool environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dependencies: async: '>=2.5.0-nullsafety <2.5.0' From e3c69b9be3add6635a22564e592803cd4e2f1c9b Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Nov 2020 20:06:33 -0800 Subject: [PATCH 158/281] Remove unused dart:async imports. As of Dart 2.1, Future/Stream have been exported from dart:core. --- pkgs/package_config/test/legacy/discovery_analysis_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/package_config/test/legacy/discovery_analysis_test.dart b/pkgs/package_config/test/legacy/discovery_analysis_test.dart index 4be636d13..7554d85d9 100644 --- a/pkgs/package_config/test/legacy/discovery_analysis_test.dart +++ b/pkgs/package_config/test/legacy/discovery_analysis_test.dart @@ -6,7 +6,6 @@ @TestOn('vm') library package_config.discovery_analysis_test; -import "dart:async"; import "dart:io"; import "package:package_config/discovery_analysis.dart"; From e4fcf2cb1c3c7ed2fdab609b903f643d9e5a4736 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 11 Nov 2020 08:19:35 -0800 Subject: [PATCH 159/281] Update analysis_options.yaml --- pkgs/pool/analysis_options.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 986bccc6c..ae67bc00b 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -4,9 +4,6 @@ analyzer: strong-mode: implicit-casts: false - enable-experiment: - - non-nullable - linter: rules: - avoid_function_literals_in_foreach_calls From 92e0d59f2d5096313a44e10ec3c3e534eff6d91c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 12 Nov 2020 17:43:24 -0800 Subject: [PATCH 160/281] Delete .test_config (dart-lang/pool#47) --- pkgs/pool/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/pool/.test_config diff --git a/pkgs/pool/.test_config b/pkgs/pool/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/pool/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file From c86d4c98c8286e2fc7263df3407834d5f3c5f612 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Wed, 2 Dec 2020 16:23:00 +0100 Subject: [PATCH 161/281] Migrate to null safety (dart-lang/package_config#93) * Migrate non-deprecated libraries to null safety. * Major version increment, removing deprecated APIs. This is the null safe, non-deprecated API for package_config.json file manipulation. Also address dart-lang/package_config#86. --- pkgs/package_config/CHANGELOG.md | 5 + pkgs/package_config/README.md | 9 +- pkgs/package_config/analysis_options.yaml | 1 - pkgs/package_config/lib/discovery.dart | 226 ------------ .../lib/discovery_analysis.dart | 167 --------- pkgs/package_config/lib/package_config.dart | 23 +- pkgs/package_config/lib/packages.dart | 96 ----- pkgs/package_config/lib/packages_file.dart | 232 ------------ pkgs/package_config/lib/src/discovery.dart | 14 +- pkgs/package_config/lib/src/errors.dart | 7 +- .../lib/src/package_config.dart | 54 +-- .../lib/src/package_config_impl.dart | 82 +++-- .../lib/src/package_config_io.dart | 39 ++- .../lib/src/package_config_json.dart | 91 ++--- .../package_config/lib/src/packages_file.dart | 4 +- .../package_config/lib/src/packages_impl.dart | 128 ------- .../lib/src/packages_io_impl.dart | 46 --- pkgs/package_config/lib/src/util.dart | 4 +- pkgs/package_config/lib/src/util_io.dart | 8 +- pkgs/package_config/pubspec.yaml | 55 ++- pkgs/package_config/test/discovery_test.dart | 6 +- .../test/discovery_uri_test.dart | 8 +- pkgs/package_config/test/legacy/all.dart | 20 -- .../test/legacy/discovery_analysis_test.dart | 127 ------- .../test/legacy/discovery_test.dart | 329 ------------------ .../test/legacy/parse_test.dart | 246 ------------- .../test/legacy/parse_write_test.dart | 133 ------- pkgs/package_config/test/parse_test.dart | 48 +-- pkgs/package_config/test/src/util.dart | 10 +- pkgs/package_config/test/src/util_io.dart | 16 +- 30 files changed, 275 insertions(+), 1959 deletions(-) delete mode 100644 pkgs/package_config/lib/discovery.dart delete mode 100644 pkgs/package_config/lib/discovery_analysis.dart delete mode 100644 pkgs/package_config/lib/packages.dart delete mode 100644 pkgs/package_config/lib/packages_file.dart delete mode 100644 pkgs/package_config/lib/src/packages_impl.dart delete mode 100644 pkgs/package_config/lib/src/packages_io_impl.dart delete mode 100644 pkgs/package_config/test/legacy/all.dart delete mode 100644 pkgs/package_config/test/legacy/discovery_analysis_test.dart delete mode 100644 pkgs/package_config/test/legacy/discovery_test.dart delete mode 100644 pkgs/package_config/test/legacy/parse_test.dart delete mode 100644 pkgs/package_config/test/legacy/parse_write_test.dart diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 6dcae80cf..32ff3f17f 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.0 + +- Migrate to null safety. +- Remove legacy APIs. + ## 1.9.3 - Fix `Package` constructor not accepting relative `packageUriRoot`. diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index b47a6825b..1ad4b41c1 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -7,11 +7,12 @@ in the Package Configuration v2 [design document](https://github.com/dart-lang/l The primary libraries are * `package_config.dart`: Defines the `PackageConfig` class and other types needed to use - package configurations. + package configurations, and provides functions to find, read and + write package configuration files. -* `package_config_discovery.dart`: - Provides functions for reading configurations from files, - and writing them back out. +* `package_config_types.dart`: + Just the `PackageConfig` class and other types needed to use + package configurations. This library does not depend on `dart:io`. The package includes deprecated backwards compatible functionality to work with the `.packages` file. This functionality will not be maintained, diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml index 66639ec1a..a7854087c 100644 --- a/pkgs/package_config/analysis_options.yaml +++ b/pkgs/package_config/analysis_options.yaml @@ -6,6 +6,5 @@ include: package:pedantic/analysis_options.1.9.0.yaml analyzer: errors: annotate_overrides: ignore - curly_braces_in_flow_control_structures: ignore prefer_single_quotes: ignore use_function_type_syntax_for_parameters: ignore diff --git a/pkgs/package_config/lib/discovery.dart b/pkgs/package_config/lib/discovery.dart deleted file mode 100644 index a72bb1255..000000000 --- a/pkgs/package_config/lib/discovery.dart +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (c) 2015, 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. - -@Deprecated("Use the package_config.json based API") -library package_config.discovery; - -import "dart:io"; -import "dart:typed_data" show Uint8List; - -import "package:path/path.dart" as path; - -import "packages.dart"; -import "packages_file.dart" as pkgfile show parse; -import "src/packages_impl.dart"; -import "src/packages_io_impl.dart"; - -/// Reads a package resolution file and creates a [Packages] object from it. -/// -/// The [packagesFile] must exist and be loadable. -/// Currently that means the URI must have a `file`, `http` or `https` scheme, -/// and that the file can be loaded and its contents parsed correctly. -/// -/// If the [loader] is provided, it is used to fetch non-`file` URIs, and -/// it can support other schemes or set up more complex HTTP requests. -/// -/// This function can be used to load an explicitly configured package -/// resolution file, for example one specified using a `--packages` -/// command-line parameter. -Future loadPackagesFile(Uri packagesFile, - {Future> loader(Uri uri)}) async { - Packages parseBytes(List bytes) { - return MapPackages(pkgfile.parse(bytes, packagesFile)); - } - - if (packagesFile.scheme == "file") { - return parseBytes(await File.fromUri(packagesFile).readAsBytes()); - } - if (loader == null) { - return parseBytes(await _httpGet(packagesFile)); - } - return parseBytes(await loader(packagesFile)); -} - -/// Create a [Packages] object for a package directory. -/// -/// The [packagesDir] URI should refer to a directory. -/// Package names are resolved as relative to sub-directories of the -/// package directory. -/// -/// This function can be used for explicitly configured package directories, -/// for example one specified using a `--package-root` comand-line parameter. -Packages getPackagesDirectory(Uri packagesDir) { - if (packagesDir.scheme == "file") { - return FilePackagesDirectoryPackages(Directory.fromUri(packagesDir)); - } - if (!packagesDir.path.endsWith('/')) { - packagesDir = packagesDir.replace(path: packagesDir.path + '/'); - } - return NonFilePackagesDirectoryPackages(packagesDir); -} - -/// Discover the package configuration for a Dart script. -/// -/// The [baseUri] points to either the Dart script or its directory. -/// A package resolution strategy is found by going through the following steps, -/// and stopping when something is found. -/// -/// * Check if a `.packages` file exists in the same directory. -/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory -/// in the same directory, and resolve packages relative to that. -/// * If `baseUri`'s scheme *is* `file`: -/// * Check if a `packages` directory exists. -/// * Otherwise check each successive parent directory of `baseUri` for a -/// `.packages` file. -/// -/// If any of these tests succeed, a `Packages` class is returned. -/// Returns the constant [noPackages] if no resolution strategy is found. -/// -/// This function currently only supports `file`, `http` and `https` URIs. -/// It needs to be able to load a `.packages` file from the URI, so only -/// recognized schemes are accepted. -/// -/// To support other schemes, or more complex HTTP requests, -/// an optional [loader] function can be supplied. -/// It's called to load the `.packages` file for a non-`file` scheme. -/// The loader function returns the *contents* of the file -/// identified by the URI it's given. -/// The content should be a UTF-8 encoded `.packages` file, and must return an -/// error future if loading fails for any reason. -Future findPackages(Uri baseUri, - {Future> loader(Uri unsupportedUri)}) { - if (baseUri.scheme == "file") { - return Future.sync(() => findPackagesFromFile(baseUri)); - } else if (loader != null) { - return findPackagesFromNonFile(baseUri, loader: loader); - } else if (baseUri.scheme == "http" || baseUri.scheme == "https") { - return findPackagesFromNonFile(baseUri, loader: _httpGet); - } else { - return Future.value(Packages.noPackages); - } -} - -/// Find the location of the package resolution file/directory for a Dart file. -/// -/// Checks for a `.packages` file in the [workingDirectory]. -/// If not found, checks for a `packages` directory in the same directory. -/// If still not found, starts checking parent directories for -/// `.packages` until reaching the root directory. -/// -/// Returns a [File] object of a `.packages` file if one is found, or a -/// [Directory] object for the `packages/` directory if that is found. -FileSystemEntity _findPackagesFile(String workingDirectory) { - var dir = Directory(workingDirectory); - if (!dir.isAbsolute) dir = dir.absolute; - if (!dir.existsSync()) { - throw ArgumentError.value( - workingDirectory, "workingDirectory", "Directory does not exist."); - } - File checkForConfigFile(Directory directory) { - assert(directory.isAbsolute); - var file = File(path.join(directory.path, ".packages")); - if (file.existsSync()) return file; - return null; - } - - // Check for $cwd/.packages - var packagesCfgFile = checkForConfigFile(dir); - if (packagesCfgFile != null) return packagesCfgFile; - // Check for $cwd/packages/ - var packagesDir = Directory(path.join(dir.path, "packages")); - if (packagesDir.existsSync()) return packagesDir; - // Check for cwd(/..)+/.packages - var parentDir = dir.parent; - while (parentDir.path != dir.path) { - packagesCfgFile = checkForConfigFile(parentDir); - if (packagesCfgFile != null) break; - dir = parentDir; - parentDir = dir.parent; - } - return packagesCfgFile; -} - -/// Finds a package resolution strategy for a local Dart script. -/// -/// The [fileBaseUri] points to either a Dart script or the directory of the -/// script. The `fileBaseUri` must be a `file:` URI. -/// -/// This function first tries to locate a `.packages` file in the `fileBaseUri` -/// directory. If that is not found, it instead checks for the presence of -/// a `packages/` directory in the same place. -/// If that also fails, it starts checking parent directories for a `.packages` -/// file, and stops if it finds it. -/// Otherwise it gives up and returns [Packages.noPackages]. -Packages findPackagesFromFile(Uri fileBaseUri) { - var baseDirectoryUri = fileBaseUri; - if (!fileBaseUri.path.endsWith('/')) { - baseDirectoryUri = baseDirectoryUri.resolve("."); - } - var baseDirectoryPath = baseDirectoryUri.toFilePath(); - var location = _findPackagesFile(baseDirectoryPath); - if (location == null) return Packages.noPackages; - if (location is File) { - var fileBytes = location.readAsBytesSync(); - var map = pkgfile.parse(fileBytes, Uri.file(location.path)); - return MapPackages(map); - } - assert(location is Directory); - return FilePackagesDirectoryPackages(location); -} - -/// Finds a package resolution strategy for a Dart script. -/// -/// The [nonFileUri] points to either a Dart script or the directory of the -/// script. -/// The [nonFileUri] should not be a `file:` URI since the algorithm for -/// finding a package resolution strategy is more elaborate for `file:` URIs. -/// In that case, use [findPackagesFromFile]. -/// -/// This function first tries to locate a `.packages` file in the [nonFileUri] -/// directory. If that is not found, it instead assumes a `packages/` directory -/// in the same place. -/// -/// By default, this function only works for `http:` and `https:` URIs. -/// To support other schemes, a loader must be provided, which is used to -/// try to load the `.packages` file. The loader should return the contents -/// of the requested `.packages` file as bytes, which will be assumed to be -/// UTF-8 encoded. -Future findPackagesFromNonFile(Uri nonFileUri, - {Future> loader(Uri name)}) async { - loader ??= _httpGet; - var packagesFileUri = nonFileUri.resolve(".packages"); - - try { - var fileBytes = await loader(packagesFileUri); - var map = pkgfile.parse(fileBytes, packagesFileUri); - return MapPackages(map); - } catch (_) { - // Didn't manage to load ".packages". Assume a "packages/" directory. - var packagesDirectoryUri = nonFileUri.resolve("packages/"); - return NonFilePackagesDirectoryPackages(packagesDirectoryUri); - } -} - -/// Fetches a file over http. -Future> _httpGet(Uri uri) async { - var client = HttpClient(); - var request = await client.getUrl(uri); - var response = await request.close(); - if (response.statusCode != HttpStatus.ok) { - throw HttpException('${response.statusCode} ${response.reasonPhrase}', - uri: uri); - } - var splitContent = await response.toList(); - var totalLength = 0; - for (var list in splitContent) { - totalLength += list.length; - } - var result = Uint8List(totalLength); - var offset = 0; - for (var contentPart in splitContent) { - result.setRange(offset, offset + contentPart.length, contentPart); - offset += contentPart.length; - } - return result; -} diff --git a/pkgs/package_config/lib/discovery_analysis.dart b/pkgs/package_config/lib/discovery_analysis.dart deleted file mode 100644 index 2af07292e..000000000 --- a/pkgs/package_config/lib/discovery_analysis.dart +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Analyse a directory structure and find packages resolvers for each -/// sub-directory. -/// -/// The resolvers are generally the same that would be found by using -/// the `discovery.dart` library on each sub-directory in turn, -/// but more efficiently and with some heuristics for directories that -/// wouldn't otherwise have a package resolution strategy, or that are -/// determined to be "package directories" themselves. -@Deprecated("Use the package_config.json based API") -library package_config.discovery_analysis; - -import "dart:collection" show HashMap; -import "dart:io" show File, Directory; - -import "package:path/path.dart" as path; - -import "packages.dart"; -import "packages_file.dart" as pkgfile; -import "src/packages_impl.dart"; -import "src/packages_io_impl.dart"; - -/// Associates a [Packages] package resolution strategy with a directory. -/// -/// The package resolution applies to the directory and any sub-directory -/// that doesn't have its own overriding child [PackageContext]. -abstract class PackageContext { - /// The directory that introduced the [packages] resolver. - Directory get directory; - - /// A [Packages] resolver that applies to the directory. - /// - /// Introduced either by a `.packages` file or a `packages/` directory. - Packages get packages; - - /// Child contexts that apply to sub-directories of [directory]. - List get children; - - /// Look up the [PackageContext] that applies to a specific directory. - /// - /// The directory must be inside [directory]. - PackageContext operator [](Directory directory); - - /// A map from directory to package resolver. - /// - /// Has an entry for this package context and for each child context - /// contained in this one. - Map asMap(); - - /// Analyze [directory] and sub-directories for package resolution strategies. - /// - /// Returns a mapping from sub-directories to [Packages] objects. - /// - /// The analysis assumes that there are no `.packages` files in a parent - /// directory of `directory`. If there is, its corresponding `Packages` object - /// should be provided as `root`. - static PackageContext findAll(Directory directory, - {Packages root = Packages.noPackages}) { - if (!directory.existsSync()) { - throw ArgumentError("Directory not found: $directory"); - } - var contexts = []; - void findRoots(Directory directory) { - Packages packages; - List oldContexts; - var packagesFile = File(path.join(directory.path, ".packages")); - if (packagesFile.existsSync()) { - packages = _loadPackagesFile(packagesFile); - oldContexts = contexts; - contexts = []; - } else { - var packagesDir = Directory(path.join(directory.path, "packages")); - if (packagesDir.existsSync()) { - packages = FilePackagesDirectoryPackages(packagesDir); - oldContexts = contexts; - contexts = []; - } - } - for (var entry in directory.listSync()) { - if (entry is Directory) { - if (packages == null || !entry.path.endsWith("/packages")) { - findRoots(entry); - } - } - } - if (packages != null) { - oldContexts.add(_PackageContext(directory, packages, contexts)); - contexts = oldContexts; - } - } - - findRoots(directory); - // If the root is not itself context root, add a the wrapper context. - if (contexts.length == 1 && contexts[0].directory == directory) { - return contexts[0]; - } - return _PackageContext(directory, root, contexts); - } -} - -class _PackageContext implements PackageContext { - final Directory directory; - final Packages packages; - final List children; - _PackageContext(this.directory, this.packages, List children) - : children = List.unmodifiable(children); - - Map asMap() { - var result = HashMap(); - void recurse(_PackageContext current) { - result[current.directory] = current.packages; - for (var child in current.children) { - recurse(child); - } - } - - recurse(this); - return result; - } - - PackageContext operator [](Directory directory) { - var path = directory.path; - if (!path.startsWith(this.directory.path)) { - throw ArgumentError("Not inside $path: $directory"); - } - var current = this; - // The current path is know to agree with directory until deltaIndex. - var deltaIndex = current.directory.path.length; - List children = current.children; - var i = 0; - while (i < children.length) { - // TODO(lrn): Sort children and use binary search. - _PackageContext child = children[i]; - var childPath = child.directory.path; - if (_stringsAgree(path, childPath, deltaIndex, childPath.length)) { - deltaIndex = childPath.length; - if (deltaIndex == path.length) { - return child; - } - current = child; - children = current.children; - i = 0; - continue; - } - i++; - } - return current; - } - - static bool _stringsAgree(String a, String b, int start, int end) { - if (a.length < end || b.length < end) return false; - for (var i = start; i < end; i++) { - if (a.codeUnitAt(i) != b.codeUnitAt(i)) return false; - } - return true; - } -} - -Packages _loadPackagesFile(File file) { - var uri = Uri.file(file.path); - var bytes = file.readAsBytesSync(); - var map = pkgfile.parse(bytes, uri); - return MapPackages(map); -} diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 1113ac872..3dfd8ef29 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -3,8 +3,11 @@ // BSD-style license that can be found in the LICENSE file. /// A package configuration is a way to assign file paths to package URIs, -/// and vice-versa, -library package_config.package_config_discovery; +/// and vice-versa. +/// +/// This package provides functionality to find, read and write package +/// configurations in the [specified format](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). +library package_config.package_config; import "dart:io" show File, Directory; import "dart:typed_data" show Uint8List; @@ -39,7 +42,7 @@ export "package_config_types.dart"; /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfig(File file, - {bool preferNewest = true, void onError(Object error)}) => + {bool preferNewest = true, void onError(Object error)?}) => readAnyConfigFile(file, preferNewest, onError ?? throwError); /// Reads a specific package configuration URI. @@ -84,9 +87,9 @@ Future loadPackageConfig(File file, /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfigUri(Uri file, - {Future loader(Uri uri) /*?*/, + {Future loader(Uri uri)?, bool preferNewest = true, - void onError(Object error)}) => + void onError(Object error)?}) => readAnyConfigFileUri(file, loader, onError ?? throwError, preferNewest); /// Finds a package configuration relative to [directory]. @@ -109,8 +112,8 @@ Future loadPackageConfigUri(Uri file, /// If no [onError] is provided, errors are thrown immediately. /// /// Returns `null` if no configuration file is found. -Future findPackageConfig(Directory directory, - {bool recurse = true, void onError(Object error)}) => +Future findPackageConfig(Directory directory, + {bool recurse = true, void onError(Object error)?}) => discover.findPackageConfig(directory, recurse, onError ?? throwError); /// Finds a package configuration relative to [location]. @@ -153,10 +156,10 @@ Future findPackageConfig(Directory directory, /// If no [onError] is provided, errors are thrown immediately. /// /// Returns `null` if no configuration file is found. -Future findPackageConfigUri(Uri location, +Future findPackageConfigUri(Uri location, {bool recurse = true, - Future loader(Uri uri), - void onError(Object error)}) => + Future loader(Uri uri)?, + void onError(Object error)?}) => discover.findPackageConfigUri( location, loader, onError ?? throwError, recurse); diff --git a/pkgs/package_config/lib/packages.dart b/pkgs/package_config/lib/packages.dart deleted file mode 100644 index 203f32fdb..000000000 --- a/pkgs/package_config/lib/packages.dart +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2015, 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. - -@Deprecated("Use the package_config.json based API") -library package_config.packages; - -import "src/packages_impl.dart"; - -/// A package resolution strategy. -/// -/// Allows converting a `package:` URI to a different kind of URI. -/// -/// May also allow listing the available packages and converting -/// to a `Map` that gives the base location of each available -/// package. In some cases there is no way to find the available packages, -/// in which case [packages] and [asMap] will throw if used. -/// One such case is if the packages are resolved relative to a -/// `packages/` directory available over HTTP. -@Deprecated("Use the package_config.json based API") -abstract class Packages { - /// A [Packages] resolver containing no packages. - /// - /// This constant object is returned by [find] above if no - /// package resolution strategy is found. - static const Packages noPackages = NoPackages(); - - /// Resolve a package URI into a non-package URI. - /// - /// Translates a `package:` URI, according to the package resolution - /// strategy, into a URI that can be loaded. - /// By default, only `file`, `http` and `https` URIs are returned. - /// Custom `Packages` objects may return other URIs. - /// - /// If resolution fails because a package with the requested package name - /// is not available, the [notFound] function is called. - /// If no `notFound` function is provided, it defaults to throwing an error. - /// - /// The [packageUri] must be a valid package URI. - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}); - - /// Return the names of the available packages. - /// - /// Returns an iterable that allows iterating the names of available packages. - /// - /// Some `Packages` objects are unable to find the package names, - /// and getting `packages` from such a `Packages` object will throw. - Iterable get packages; - - /// Retrieve metadata associated with a package. - /// - /// Metadata have string keys and values, and are looked up by key. - /// - /// Returns `null` if the argument is not a valid package name, - /// or if the package is not one of the packages configured by - /// this packages object, or if the package does not have associated - /// metadata with the provided [key]. - /// - /// Not all `Packages` objects can support metadata. - /// Those will always return `null`. - String packageMetadata(String packageName, String key); - - /// Retrieve metadata associated with a library. - /// - /// If [libraryUri] is a `package:` URI, the returned value - /// is the same that would be returned by [packageMetadata] with - /// the package's name and the same key. - /// - /// If [libraryUri] is not a `package:` URI, and this [Packages] - /// object has a [defaultPackageName], then the [key] is looked - /// up on the default package instead. - /// - /// Otherwise the result is `null`. - String libraryMetadata(Uri libraryUri, String key); - - /// Return the names-to-base-URI mapping of the available packages. - /// - /// Returns a map from package name to a base URI. - /// The [resolve] method will resolve a package URI with a specific package - /// name to a path extending the base URI that this map gives for that - /// package name. - /// - /// Some `Packages` objects are unable to find the package names, - /// and calling `asMap` on such a `Packages` object will throw. - Map asMap(); - - /// The name of the "default package". - /// - /// A default package is a package that *non-package* libraries - /// may be considered part of for some purposes. - /// - /// The value is `null` if there is no default package. - /// Not all implementations of [Packages] supports a default package, - /// and will always have a `null` value for those. - String get defaultPackageName; -} diff --git a/pkgs/package_config/lib/packages_file.dart b/pkgs/package_config/lib/packages_file.dart deleted file mode 100644 index ef0b0b3ca..000000000 --- a/pkgs/package_config/lib/packages_file.dart +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2015, 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. - -@Deprecated("Use the package_config.json based API") -library package_config.packages_file; - -import "package:charcode/ascii.dart"; - -import "src/util.dart" show isValidPackageName; - -/// Parses a `.packages` file into a map from package name to base URI. -/// -/// The [source] is the byte content of a `.packages` file, assumed to be -/// UTF-8 encoded. In practice, all significant parts of the file must be ASCII, -/// so Latin-1 or Windows-1252 encoding will also work fine. -/// -/// If the file content is available as a string, its [String.codeUnits] can -/// be used as the `source` argument of this function. -/// -/// The [baseLocation] is used as a base URI to resolve all relative -/// URI references against. -/// If the content was read from a file, `baseLocation` should be the -/// location of that file. -/// -/// If [allowDefaultPackage] is set to true, an entry with an empty package name -/// is accepted. This entry does not correspond to a package, but instead -/// represents a *default package* which non-package libraries may be considered -/// part of in some cases. The value of that entry must be a valid package name. -/// -/// Returns a simple mapping from package name to package location. -/// If default package is allowed, the map maps the empty string to the default package's name. -Map parse(List source, Uri baseLocation, - {bool allowDefaultPackage = false}) { - var index = 0; - var result = {}; - while (index < source.length) { - var isComment = false; - var start = index; - var separatorIndex = -1; - var end = source.length; - var char = source[index++]; - if (char == $cr || char == $lf) { - continue; - } - if (char == $colon) { - if (!allowDefaultPackage) { - throw FormatException("Missing package name", source, index - 1); - } - separatorIndex = index - 1; - } - isComment = char == $hash; - while (index < source.length) { - char = source[index++]; - if (char == $colon && separatorIndex < 0) { - separatorIndex = index - 1; - } else if (char == $cr || char == $lf) { - end = index - 1; - break; - } - } - if (isComment) continue; - if (separatorIndex < 0) { - throw FormatException("No ':' on line", source, index - 1); - } - var packageName = String.fromCharCodes(source, start, separatorIndex); - if (packageName.isEmpty - ? !allowDefaultPackage - : !isValidPackageName(packageName)) { - throw FormatException("Not a valid package name", packageName, 0); - } - var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); - Uri packageLocation; - if (packageName.isEmpty) { - if (!isValidPackageName(packageValue)) { - throw FormatException( - "Default package entry value is not a valid package name"); - } - packageLocation = Uri(path: packageValue); - } else { - packageLocation = baseLocation.resolve(packageValue); - if (!packageLocation.path.endsWith('/')) { - packageLocation = - packageLocation.replace(path: packageLocation.path + "/"); - } - } - if (result.containsKey(packageName)) { - if (packageName.isEmpty) { - throw FormatException( - "More than one default package entry", source, start); - } - throw FormatException("Same package name occured twice", source, start); - } - result[packageName] = packageLocation; - } - return result; -} - -/// Writes the mapping to a [StringSink]. -/// -/// If [comment] is provided, the output will contain this comment -/// with `# ` in front of each line. -/// Lines are defined as ending in line feed (`'\n'`). If the final -/// line of the comment doesn't end in a line feed, one will be added. -/// -/// If [baseUri] is provided, package locations will be made relative -/// to the base URI, if possible, before writing. -/// -/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an -/// empty string mapping to the _default package name_. -/// -/// All the keys of [packageMapping] must be valid package names, -/// and the values must be URIs that do not have the `package:` scheme. -void write(StringSink output, Map packageMapping, - {Uri baseUri, String comment, bool allowDefaultPackage = false}) { - ArgumentError.checkNotNull(allowDefaultPackage, 'allowDefaultPackage'); - - if (baseUri != null && !baseUri.isAbsolute) { - throw ArgumentError.value(baseUri, "baseUri", "Must be absolute"); - } - - if (comment != null) { - var lines = comment.split('\n'); - if (lines.last.isEmpty) lines.removeLast(); - for (var commentLine in lines) { - output.write('# '); - output.writeln(commentLine); - } - } else { - output.write("# generated by package:package_config at "); - output.write(DateTime.now()); - output.writeln(); - } - - packageMapping.forEach((String packageName, Uri uri) { - // If [packageName] is empty then [uri] is the _default package name_. - if (allowDefaultPackage && packageName.isEmpty) { - final defaultPackageName = uri.toString(); - if (!isValidPackageName(defaultPackageName)) { - throw ArgumentError.value( - defaultPackageName, - 'defaultPackageName', - '"$defaultPackageName" is not a valid package name', - ); - } - output.write(':'); - output.write(defaultPackageName); - output.writeln(); - return; - } - // Validate packageName. - if (!isValidPackageName(packageName)) { - throw ArgumentError('"$packageName" is not a valid package name'); - } - if (uri.scheme == "package") { - throw ArgumentError.value( - "Package location must not be a package: URI", uri.toString()); - } - output.write(packageName); - output.write(':'); - // If baseUri provided, make uri relative. - if (baseUri != null) { - uri = _relativize(uri, baseUri); - } - if (!uri.path.endsWith('/')) { - uri = uri.replace(path: uri.path + '/'); - } - output.write(uri); - output.writeln(); - }); -} - -/// Attempts to return a relative URI for [uri]. -/// -/// The result URI satisfies `baseUri.resolveUri(result) == uri`, -/// but may be relative. -/// The `baseUri` must be absolute. -Uri _relativize(Uri uri, Uri baseUri) { - assert(baseUri.isAbsolute); - if (uri.hasQuery || uri.hasFragment) { - uri = Uri( - scheme: uri.scheme, - userInfo: uri.hasAuthority ? uri.userInfo : null, - host: uri.hasAuthority ? uri.host : null, - port: uri.hasAuthority ? uri.port : null, - path: uri.path); - } - - // Already relative. We assume the caller knows what they are doing. - if (!uri.isAbsolute) return uri; - - if (baseUri.scheme != uri.scheme) { - return uri; - } - - // If authority differs, we could remove the scheme, but it's not worth it. - if (uri.hasAuthority != baseUri.hasAuthority) return uri; - if (uri.hasAuthority) { - if (uri.userInfo != baseUri.userInfo || - uri.host.toLowerCase() != baseUri.host.toLowerCase() || - uri.port != baseUri.port) { - return uri; - } - } - - baseUri = baseUri.normalizePath(); - var base = baseUri.pathSegments.toList(); - if (base.isNotEmpty) { - base = List.from(base)..removeLast(); - } - uri = uri.normalizePath(); - var target = uri.pathSegments.toList(); - if (target.isNotEmpty && target.last.isEmpty) target.removeLast(); - var index = 0; - while (index < base.length && index < target.length) { - if (base[index] != target[index]) { - break; - } - index++; - } - if (index == base.length) { - if (index == target.length) { - return Uri(path: "./"); - } - return Uri(path: target.skip(index).join('/')); - } else if (index > 0) { - return Uri( - path: '../' * (base.length - index) + target.skip(index).join('/')); - } else { - return uri; - } -} diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 8ac6a0128..a3e01d710 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -32,7 +32,7 @@ final Uri parentPath = Uri(path: ".."); /// If any of these tests succeed, a `PackageConfig` class is returned. /// Returns `null` if no configuration was found. If a configuration /// is needed, then the caller can supply [PackageConfig.empty]. -Future findPackageConfig( +Future findPackageConfig( Directory baseDirectory, bool recursive, void onError(Object error)) async { var directory = baseDirectory; if (!directory.isAbsolute) directory = directory.absolute; @@ -53,10 +53,10 @@ Future findPackageConfig( } /// Similar to [findPackageConfig] but based on a URI. -Future findPackageConfigUri( +Future findPackageConfigUri( Uri location, - Future loader(Uri uri) /*?*/, - void onError(Object error) /*?*/, + Future loader(Uri uri)?, + void onError(Object error), bool recursive) async { if (location.isScheme("package")) { onError(PackageConfigArgumentError( @@ -102,7 +102,7 @@ Future findPackageConfigUri( /// If [onError] is supplied, parsing errors are reported using that, and /// a best-effort attempt is made to return a package configuration. /// This may be the empty package configuration. -Future findPackagConfigInDirectory( +Future findPackagConfigInDirectory( Directory directory, void onError(Object error)) async { var packageConfigFile = await checkForPackageConfigJsonFile(directory); if (packageConfigFile != null) { @@ -115,7 +115,7 @@ Future findPackagConfigInDirectory( return null; } -Future /*?*/ checkForPackageConfigJsonFile(Directory directory) async { +Future checkForPackageConfigJsonFile(Directory directory) async { assert(directory.isAbsolute); var file = File(pathJoin(directory.path, ".dart_tool", "package_config.json")); @@ -123,7 +123,7 @@ Future /*?*/ checkForPackageConfigJsonFile(Directory directory) async { return null; } -Future checkForDotPackagesFile(Directory directory) async { +Future checkForDotPackagesFile(Directory directory) async { var file = File(pathJoin(directory.path, ".packages")); if (await file.exists()) return file; return null; diff --git a/pkgs/package_config/lib/src/errors.dart b/pkgs/package_config/lib/src/errors.dart index c9736177c..f3515711d 100644 --- a/pkgs/package_config/lib/src/errors.dart +++ b/pkgs/package_config/lib/src/errors.dart @@ -12,7 +12,7 @@ abstract class PackageConfigError { class PackageConfigArgumentError extends ArgumentError implements PackageConfigError { - PackageConfigArgumentError(Object /*?*/ value, String name, String message) + PackageConfigArgumentError(Object? value, String name, String message) : super.value(value, name, message); PackageConfigArgumentError.from(ArgumentError error) @@ -21,8 +21,7 @@ class PackageConfigArgumentError extends ArgumentError class PackageConfigFormatException extends FormatException implements PackageConfigError { - PackageConfigFormatException(String message, Object /*?*/ source, - [int /*?*/ offset]) + PackageConfigFormatException(String message, Object? source, [int? offset]) : super(message, source, offset); PackageConfigFormatException.from(FormatException exception) @@ -30,4 +29,4 @@ class PackageConfigFormatException extends FormatException } /// The default `onError` handler. -void /*Never*/ throwError(Object error) => throw error; +Never throwError(Object error) => throw error; diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 30c758a96..63d01eacd 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -50,7 +50,7 @@ abstract class PackageConfig { /// [PackageConfig.extraData] of the created configuration. /// /// The version of the resulting configuration is always [maxVersion]. - factory PackageConfig(Iterable packages, {dynamic extraData}) => + factory PackageConfig(Iterable packages, {Object? extraData}) => SimplePackageConfig(maxVersion, packages, extraData); /// Parses a package configuration file. @@ -67,10 +67,10 @@ abstract class PackageConfig { /// the configuration are reported by calling [onError] instead of /// throwing, and parser makes a *best effort* attempt to continue /// despite the error. The input must still be valid JSON. - /// The result may be a [PackageConfig.empty] if there is no way to + /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. static PackageConfig parseBytes(Uint8List bytes, Uri baseUri, - {void onError(Object error)}) => + {void onError(Object error)?}) => parsePackageConfigBytes(bytes, baseUri, onError ?? throwError); /// Parses a package configuration file. @@ -87,10 +87,10 @@ abstract class PackageConfig { /// the configuration are reported by calling [onError] instead of /// throwing, and parser makes a *best effort* attempt to continue /// despite the error. The input must still be valid JSON. - /// The result may be a [PackageConfig.empty] if there is no way to + /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. static PackageConfig parseString(String configuration, Uri baseUri, - {void onError(Object error)}) => + {void onError(Object error)?}) => parsePackageConfigString(configuration, baseUri, onError ?? throwError); /// Parses the JSON data of a package configuration file. @@ -108,10 +108,10 @@ abstract class PackageConfig { /// the configuration are reported by calling [onError] instead of /// throwing, and parser makes a *best effort* attempt to continue /// despite the error. The input must still be valid JSON. - /// The result may be a [PackageConfig.empty] if there is no way to + /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. - static PackageConfig parseJson(dynamic jsonData, Uri baseUri, - {void onError(Object error)}) => + static PackageConfig parseJson(Object? jsonData, Uri baseUri, + {void onError(Object error)?}) => parsePackageConfigJson(jsonData, baseUri, onError ?? throwError); /// Writes a configuration file for this configuration on [output]. @@ -119,7 +119,7 @@ abstract class PackageConfig { /// If [baseUri] is provided, URI references in the generated file /// will be made relative to [baseUri] where possible. static void writeBytes(PackageConfig configuration, Sink output, - [Uri /*?*/ baseUri]) { + [Uri? baseUri]) { writePackageConfigJsonUtf8(configuration, baseUri, output); } @@ -128,7 +128,7 @@ abstract class PackageConfig { /// If [baseUri] is provided, URI references in the generated file /// will be made relative to [baseUri] where possible. static void writeString(PackageConfig configuration, StringSink output, - [Uri /*?*/ baseUri]) { + [Uri? baseUri]) { writePackageConfigJsonString(configuration, baseUri, output); } @@ -136,8 +136,8 @@ abstract class PackageConfig { /// /// If [baseUri] is provided, URI references in the generated data /// will be made relative to [baseUri] where possible. - static Map toJson(PackageConfig configuration, - [Uri /*?*/ baseUri]) => + static Map toJson(PackageConfig configuration, + [Uri? baseUri]) => packageConfigToJson(configuration, baseUri); /// The configuration version number. @@ -162,7 +162,7 @@ abstract class PackageConfig { /// Returns the [Package] fron [packages] with [packageName] as /// [Package.name]. Returns `null` if the package is not available in the /// current configuration. - Package /*?*/ operator [](String packageName); + Package? operator [](String packageName); /// Provides the associated package for a specific [file] (or directory). /// @@ -171,7 +171,7 @@ abstract class PackageConfig { /// of the [file]'s location. /// /// Returns `null` if the file does not belong to any package. - Package /*?*/ packageOf(Uri file); + Package? packageOf(Uri file); /// Resolves a `package:` URI to a non-package URI /// @@ -188,7 +188,7 @@ abstract class PackageConfig { /// in this package configuration. /// Returns the remaining path of the package URI resolved relative to the /// [Package.packageUriRoot] of the corresponding package. - Uri /*?*/ resolve(Uri packageUri); + Uri? resolve(Uri packageUri); /// The package URI which resolves to [nonPackageUri]. /// @@ -199,14 +199,14 @@ abstract class PackageConfig { /// /// Returns a package URI which [resolve] will convert to [nonPackageUri], /// if any such URI exists. Returns `null` if no such package URI exists. - Uri /*?*/ toPackageUri(Uri nonPackageUri); + Uri? toPackageUri(Uri nonPackageUri); /// Extra data associated with the package configuration. /// /// The data may be in any format, depending on who introduced it. /// The standard `packjage_config.json` file storage will only store /// JSON-like list/map data structures. - dynamic get extraData; + Object? get extraData; } /// Configuration data for a single package. @@ -227,11 +227,11 @@ abstract class Package { /// If [extraData] is supplied, it will be available as the /// [Package.extraData] of the created package. factory Package(String name, Uri root, - {Uri /*?*/ packageUriRoot, - LanguageVersion /*?*/ languageVersion, - dynamic extraData}) => + {Uri? packageUriRoot, + LanguageVersion? languageVersion, + Object? extraData}) => SimplePackage.validate( - name, root, packageUriRoot, languageVersion, extraData, throwError); + name, root, packageUriRoot, languageVersion, extraData, throwError)!; /// The package-name of the package. String get name; @@ -263,14 +263,18 @@ abstract class Package { /// Dart files in the package. /// A package version is defined by two non-negative numbers, /// the *major* and *minor* version numbers. - LanguageVersion /*?*/ get languageVersion; + /// + /// A package may have no language version associated with it + /// in the package configuration, in which case tools should + /// use a default behavior for the package. + LanguageVersion? get languageVersion; /// Extra data associated with the specific package. /// /// The data may be in any format, depending on who introduced it. - /// The standard `packjage_config.json` file storage will only store + /// The standard `package_config.json` file storage will only store /// JSON-like list/map data structures. - dynamic get extraData; + Object? get extraData; } /// A language version. @@ -307,7 +311,7 @@ abstract class LanguageVersion implements Comparable { /// If [onError] is not supplied, it defaults to throwing the exception. /// If the call does not throw, then an [InvalidLanguageVersion] is returned /// containing the original [source]. - static LanguageVersion parse(String source, {void onError(Object error)}) => + static LanguageVersion parse(String source, {void onError(Object error)?}) => parseLanguageVersion(source, onError ?? throwError); /// The major language version. diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 9e23af063..5c6b7f728 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -14,10 +14,10 @@ class SimplePackageConfig implements PackageConfig { final int version; final Map _packages; final PackageTree _packageTree; - final dynamic extraData; + final Object? extraData; factory SimplePackageConfig(int version, Iterable packages, - [dynamic extraData, void onError(Object error)]) { + [Object? extraData, void onError(Object error)?]) { onError ??= throwError; var validVersion = _validateVersion(version, onError); var sortedPackages = [...packages]..sort(_compareRoot); @@ -53,11 +53,7 @@ class SimplePackageConfig implements PackageConfig { var packageNames = {}; var tree = MutablePackageTree(); for (var originalPackage in packages) { - if (originalPackage == null) { - onError(ArgumentError.notNull("element of packages")); - continue; - } - SimplePackage package; + SimplePackage? package; if (originalPackage is! SimplePackage) { // SimplePackage validates these properties. package = SimplePackage.validate( @@ -68,7 +64,7 @@ class SimplePackageConfig implements PackageConfig { originalPackage.extraData, (error) { if (error is PackageConfigArgumentError) { onError(PackageConfigArgumentError(packages, "packages", - "Package ${package.name}: ${error.message}")); + "Package ${package!.name}: ${error.message}")); } else { onError(error); } @@ -92,7 +88,7 @@ class SimplePackageConfig implements PackageConfig { onError(PackageConfigArgumentError( originalPackages, "packages", - "Packages ${package.name} and ${existingPackage.name} " + "Packages ${package!.name} and ${existingPackage.name} " "have the same root directory: ${package.root}.\n")); } else { assert(error.isPackageRootConflict); @@ -100,7 +96,7 @@ class SimplePackageConfig implements PackageConfig { onError(PackageConfigArgumentError( originalPackages, "packages", - "Package ${package.name} is inside the package URI root of " + "Package ${package!.name} is inside the package URI root of " "package ${existingPackage.name}.\n" "${existingPackage.name} URI root: " "${existingPackage.packageUriRoot}\n" @@ -117,7 +113,7 @@ class SimplePackageConfig implements PackageConfig { Iterable get packages => _packages.values; - Package /*?*/ operator [](String packageName) => _packages[packageName]; + Package? operator [](String packageName) => _packages[packageName]; /// Provides the associated package for a specific [file] (or directory). /// @@ -125,15 +121,15 @@ class SimplePackageConfig implements PackageConfig { /// That is, the [Package.rootUri] directory is a parent directory /// of the [file]'s location. /// Returns `null` if the file does not belong to any package. - Package /*?*/ packageOf(Uri file) => _packageTree.packageOf(file); + Package? packageOf(Uri file) => _packageTree.packageOf(file); - Uri /*?*/ resolve(Uri packageUri) { + Uri? resolve(Uri packageUri) { var packageName = checkValidPackageUri(packageUri, "packageUri"); - return _packages[packageName]?.packageUriRoot?.resolveUri( + return _packages[packageName]?.packageUriRoot.resolveUri( Uri(path: packageUri.path.substring(packageName.length + 1))); } - Uri /*?*/ toPackageUri(Uri nonPackageUri) { + Uri? toPackageUri(Uri nonPackageUri) { if (nonPackageUri.isScheme("package")) { throw PackageConfigArgumentError( nonPackageUri, "nonPackageUri", "Must not be a package URI"); @@ -161,8 +157,8 @@ class SimplePackage implements Package { final String name; final Uri root; final Uri packageUriRoot; - final LanguageVersion /*?*/ languageVersion; - final dynamic extraData; + final LanguageVersion? languageVersion; + final Object? extraData; SimplePackage._(this.name, this.root, this.packageUriRoot, this.languageVersion, this.extraData); @@ -182,12 +178,12 @@ class SimplePackage implements Package { /// /// Returns `null` if the input is invalid and an approximately valid package /// cannot be salvaged from the input. - static SimplePackage /*?*/ validate( + static SimplePackage? validate( String name, Uri root, - Uri packageUriRoot, - LanguageVersion /*?*/ languageVersion, - dynamic extraData, + Uri? packageUriRoot, + LanguageVersion? languageVersion, + Object? extraData, void onError(Object error)) { var fatalError = false; var invalidIndex = checkPackageName(name); @@ -244,7 +240,7 @@ class SimplePackage implements Package { /// Reports a format exception on [onError] if not, or if the numbers /// are too large (at most 32-bit signed integers). LanguageVersion parseLanguageVersion( - String source, void onError(Object error)) { + String? source, void onError(Object error)) { var index = 0; // Reads a positive decimal numeral. Returns the value of the numeral, // or a negative number in case of an error. @@ -254,7 +250,7 @@ LanguageVersion parseLanguageVersion( // It is a recoverable error if the numeral starts with leading zeros. int readNumeral() { const maxValue = 0x7FFFFFFF; - if (index == source.length) { + if (index == source!.length) { onError(PackageConfigFormatException("Missing number", source, index)); return -1; } @@ -291,7 +287,7 @@ LanguageVersion parseLanguageVersion( if (major < 0) { return SimpleInvalidLanguageVersion(source); } - if (index == source.length || source.codeUnitAt(index) != $dot) { + if (index == source!.length || source.codeUnitAt(index) != $dot) { onError(PackageConfigFormatException("Missing '.'", source, index)); return SimpleInvalidLanguageVersion(source); } @@ -319,7 +315,7 @@ abstract class _SimpleLanguageVersionBase implements LanguageVersion { class SimpleLanguageVersion extends _SimpleLanguageVersionBase { final int major; final int minor; - String /*?*/ _source; + String? _source; SimpleLanguageVersion(this.major, this.minor, this._source); bool operator ==(Object other) => @@ -332,17 +328,17 @@ class SimpleLanguageVersion extends _SimpleLanguageVersionBase { class SimpleInvalidLanguageVersion extends _SimpleLanguageVersionBase implements InvalidLanguageVersion { - final String _source; + final String? _source; SimpleInvalidLanguageVersion(this._source); int get major => -1; int get minor => -1; - String toString() => _source; + String toString() => _source!; } abstract class PackageTree { Iterable get allPackages; - SimplePackage /*?*/ packageOf(Uri file); + SimplePackage? packageOf(Uri file); } /// Packages of a package configuration ordered by root path. @@ -373,12 +369,17 @@ class MutablePackageTree implements PackageTree { /// Indexed by [Package.name]. /// If a package has no nested packages (which is most often the case), /// there is no tree object associated with it. - Map /*?*/ _packageChildren; + Map? _packageChildren; Iterable get allPackages sync* { - for (var package in packages) yield package; - if (_packageChildren != null) { - for (var tree in _packageChildren.values) yield* tree.allPackages; + for (var package in packages) { + yield package; + } + var children = _packageChildren; + if (children != null) { + for (var tree in children.values) { + yield* tree.allPackages; + } } } @@ -424,7 +425,7 @@ class MutablePackageTree implements PackageTree { packages.add(package); } - SimplePackage /*?*/ packageOf(Uri file) { + SimplePackage? packageOf(Uri file) { return findPackageOf(0, file.toString()); } @@ -434,7 +435,7 @@ class MutablePackageTree implements PackageTree { /// /// Assumes the first [start] characters of path agrees with all /// the packages at this level of the tree. - SimplePackage /*?*/ findPackageOf(int start, String path) { + SimplePackage? findPackageOf(int start, String path) { for (var childPackage in packages) { var childPath = childPackage.root.toString(); if (_beginsWith(start, childPath, path)) { @@ -447,14 +448,9 @@ class MutablePackageTree implements PackageTree { _beginsWith(childPathLength, uriRoot, path)) { return childPackage; } - // Otherwise add [package] as child of [childPackage]. - // TODO(lrn): When NNBD comes, convert to: - // return _packageChildren?[childPackage.name] - // ?.packageOf(childPathLength, path) ?? childPackage; - if (_packageChildren == null) return childPackage; - var childTree = _packageChildren[childPackage.name]; - if (childTree == null) return childPackage; - return childTree.findPackageOf(childPathLength, path) ?? childPackage; + return _packageChildren?[childPackage.name] + ?.findPackageOf(childPathLength, path) ?? + childPackage; } } return null; @@ -474,7 +470,7 @@ class EmptyPackageTree implements PackageTree { Iterable get allPackages => const Iterable.empty(); - SimplePackage packageOf(Uri file) => null; + SimplePackage? packageOf(Uri file) => null; } /// Checks whether [longerPath] begins with [parentPath]. diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index bfbb1e373..d3e59be47 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -15,6 +15,21 @@ import "packages_file.dart" as packages_file; import "util.dart"; import "util_io.dart"; +/// Name of directory where Dart tools store their configuration. +/// +/// Directory is created in the package root directory. +const dartToolDirName = ".dart_tool"; + +/// Name of file containing new package configuration data. +/// +/// File is stored in the dart tool directory. +const packageConfigFileName = "package_config.json"; + +/// Name of file containing legacy package configuration data. +/// +/// File is stored in the package root directory. +const packagesFileName = ".packages"; + /// Reads a package configuration file. /// /// Detects whether the [file] is a version one `.packages` file or @@ -29,9 +44,9 @@ import "util_io.dart"; /// The file must exist and be a normal file. Future readAnyConfigFile( File file, bool preferNewest, void onError(Object error)) async { - if (preferNewest && fileName(file.path) == ".packages") { - var alternateFile = - File(pathJoin(dirName(file.path), ".dart_tool", "package_config.json")); + if (preferNewest && fileName(file.path) == packagesFileName) { + var alternateFile = File( + pathJoin(dirName(file.path), dartToolDirName, packageConfigFileName)); if (alternateFile.existsSync()) { return await readPackageConfigJsonFile(alternateFile, onError); } @@ -49,7 +64,7 @@ Future readAnyConfigFile( /// Like [readAnyConfigFile] but uses a URI and an optional loader. Future readAnyConfigFileUri( Uri file, - Future loader(Uri uri) /*?*/, + Future loader(Uri uri)?, void onError(Object error), bool preferNewest) async { if (file.isScheme("package")) { @@ -62,9 +77,9 @@ Future readAnyConfigFileUri( } loader = defaultLoader; } - if (preferNewest && file.pathSegments.last == ".packages") { - var alternateFile = file.resolve(".dart_tool/package_config.json"); - Uint8List /*?*/ bytes; + if (preferNewest && file.pathSegments.last == packagesFileName) { + var alternateFile = file.resolve("$dartToolDirName/$packageConfigFileName"); + Uint8List? bytes; try { bytes = await loader(alternateFile); } catch (e) { @@ -75,7 +90,7 @@ Future readAnyConfigFileUri( return parsePackageConfigBytes(bytes, alternateFile, onError); } } - Uint8List /*?*/ bytes; + Uint8List? bytes; try { bytes = await loader(file); } catch (e) { @@ -131,15 +146,17 @@ Future readDotPackagesFile( Future writePackageConfigJsonFile( PackageConfig config, Directory targetDirectory) async { // Write .dart_tool/package_config.json first. - var file = - File(pathJoin(targetDirectory.path, ".dart_tool", "package_config.json")); + var dartToolDir = Directory(pathJoin(targetDirectory.path, dartToolDirName)); + await dartToolDir.create(recursive: true); + var file = File(pathJoin(dartToolDir.path, packageConfigFileName)); var baseUri = file.uri; + var sink = file.openWrite(encoding: utf8); writePackageConfigJsonUtf8(config, baseUri, sink); var doneJson = sink.close(); // Write .packages too. - file = File(pathJoin(targetDirectory.path, ".packages")); + file = File(pathJoin(targetDirectory.path, packagesFileName)); baseUri = file.uri; sink = file.openWrite(encoding: utf8); writeDotPackages(config, baseUri, sink); diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 27abf505c..25b04c4d1 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -59,10 +59,10 @@ PackageConfig parsePackageConfigString( /// Creates a [PackageConfig] from a parsed JSON-like object structure. /// -/// The [json] argument must be a JSON object (`Map`) +/// The [json] argument must be a JSON object (`Map`) /// containing a `"configVersion"` entry with an integer value in the range /// 1 to [PackageConfig.maxVersion], -/// and with a `"packages"` entry which is a JSON array (`List`) +/// and with a `"packages"` entry which is a JSON array (`List`) /// containing JSON objects which each has the following properties: /// /// * `"name"`: The package name as a string. @@ -80,7 +80,7 @@ PackageConfig parsePackageConfigString( /// The [baseLocation] is used as base URI to resolve the "rootUri" /// URI referencestring. PackageConfig parsePackageConfigJson( - dynamic json, Uri baseLocation, void onError(Object error)) { + Object? json, Uri baseLocation, void onError(Object error)) { if (!baseLocation.hasScheme || baseLocation.isScheme("package")) { throw PackageConfigArgumentError(baseLocation.toString(), "baseLocation", "Must be an absolute non-package: URI"); @@ -97,10 +97,10 @@ PackageConfig parsePackageConfigJson( return "object"; } - T checkType(dynamic value, String name, [String /*?*/ packageName]) { + T? checkType(Object? value, String name, [String? packageName]) { if (value is T) return value; - // The only types we are called with are [int], [String], [List] - // and Map. Recognize which to give a better error message. + // The only types we are called with are [int], [String], [List] + // and Map. Recognize which to give a better error message. var message = "$name${packageName != null ? " of package $packageName" : ""}" " is not a JSON ${typeName()}"; @@ -108,12 +108,12 @@ PackageConfig parsePackageConfigJson( return null; } - Package /*?*/ parsePackage(Map entry) { - String /*?*/ name; - String /*?*/ rootUri; - String /*?*/ packageUri; - String /*?*/ languageVersion; - Map /*?*/ extraData; + Package? parsePackage(Map entry) { + String? name; + String? rootUri; + String? packageUri; + String? languageVersion; + Map? extraData; var hasName = false; var hasRoot = false; var hasVersion = false; @@ -146,22 +146,22 @@ PackageConfig parsePackageConfigJson( onError(PackageConfigFormatException("Missing rootUri entry", entry)); } if (name == null || rootUri == null) return null; - var root = baseLocation.resolve(rootUri); + var root = baseLocation.resolve(rootUri!); if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/"); var packageRoot = root; - if (packageUri != null) packageRoot = root.resolve(packageUri); + if (packageUri != null) packageRoot = root.resolve(packageUri!); if (!packageRoot.path.endsWith("/")) { packageRoot = packageRoot.replace(path: packageRoot.path + "/"); } - LanguageVersion /*?*/ version; + LanguageVersion? version; if (languageVersion != null) { version = parseLanguageVersion(languageVersion, onError); } else if (hasVersion) { version = SimpleInvalidLanguageVersion("invalid"); } - return SimplePackage.validate(name, root, packageRoot, version, extraData, + return SimplePackage.validate(name!, root, packageRoot, version, extraData, (error) { if (error is ArgumentError) { onError( @@ -172,22 +172,22 @@ PackageConfig parsePackageConfigJson( }); } - var map = checkType>(json, "value"); + var map = checkType>(json, "value"); if (map == null) return const SimplePackageConfig.empty(); - Map /*?*/ extraData; - List /*?*/ packageList; - int /*?*/ configVersion; + Map? extraData; + List? packageList; + int? configVersion; map.forEach((key, value) { switch (key) { case _configVersionKey: configVersion = checkType(value, _configVersionKey) ?? 2; break; case _packagesKey: - var packageArray = checkType>(value, _packagesKey) ?? []; + var packageArray = checkType>(value, _packagesKey) ?? []; var packages = []; for (var package in packageArray) { var packageMap = - checkType>(package, "package entry"); + checkType>(package, "package entry"); if (packageMap != null) { var entry = parsePackage(packageMap); if (entry != null) { @@ -210,7 +210,7 @@ PackageConfig parsePackageConfigJson( onError(PackageConfigFormatException("Missing packages list", json)); packageList = []; } - return SimplePackageConfig(configVersion, packageList, extraData, (error) { + return SimplePackageConfig(configVersion!, packageList!, extraData, (error) { if (error is ArgumentError) { onError(PackageConfigFormatException(error.message, error.invalidValue)); } else { @@ -222,26 +222,26 @@ PackageConfig parsePackageConfigJson( final _jsonUtf8Encoder = JsonUtf8Encoder(" "); void writePackageConfigJsonUtf8( - PackageConfig config, Uri baseUri, Sink> output) { + PackageConfig config, Uri? baseUri, Sink> output) { // Can be optimized. var data = packageConfigToJson(config, baseUri); output.add(_jsonUtf8Encoder.convert(data) as Uint8List); } void writePackageConfigJsonString( - PackageConfig config, Uri baseUri, StringSink output) { + PackageConfig config, Uri? baseUri, StringSink output) { // Can be optimized. var data = packageConfigToJson(config, baseUri); output.write(JsonEncoder.withIndent(" ").convert(data) as Uint8List); } -Map packageConfigToJson(PackageConfig config, Uri baseUri) => - { +Map packageConfigToJson(PackageConfig config, Uri? baseUri) => + { ...?_extractExtraData(config.extraData, _topNames), _configVersionKey: PackageConfig.maxVersion, _packagesKey: [ for (var package in config.packages) - { + { _nameKey: package.name, _rootUriKey: relativizeUri(package.root, baseUri).toString(), if (package.root != package.packageUriRoot) @@ -259,15 +259,15 @@ Map packageConfigToJson(PackageConfig config, Uri baseUri) => void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) { var extraData = config.extraData; // Write .packages too. - String /*?*/ comment; - if (extraData != null) { - String /*?*/ generator = extraData[_generatorKey]; - if (generator != null) { - String /*?*/ generated = extraData[_generatedKey]; - String /*?*/ generatorVersion = extraData[_generatorVersionKey]; + String? comment; + if (extraData is Map) { + var generator = extraData[_generatorKey]; + if (generator is String) { + var generated = extraData[_generatedKey]; + var generatorVersion = extraData[_generatorVersionKey]; comment = "Generated by $generator" - "${generatorVersion != null ? " $generatorVersion" : ""}" - "${generated != null ? " on $generated" : ""}."; + "${generatorVersion is String ? " $generatorVersion" : ""}" + "${generated is String ? " on $generated" : ""}."; } } packages_file.write(output, config, baseUri: baseUri, comment: comment); @@ -277,20 +277,21 @@ void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) { /// /// If the value contains any of the [reservedNames] for the current context, /// entries with that name in the extra data are dropped. -Map /*?*/ _extractExtraData( - dynamic data, Iterable reservedNames) { - if (data is Map) { +Map? _extractExtraData( + Object? data, Iterable reservedNames) { + if (data is Map) { if (data.isEmpty) return null; for (var name in reservedNames) { if (data.containsKey(name)) { - data = { + var filteredData = { for (var key in data.keys) if (!reservedNames.contains(key)) key: data[key] }; - if (data.isEmpty) return null; - for (var value in data.values) { + if (filteredData.isEmpty) return null; + for (var value in filteredData.values) { if (!_validateJson(value)) return null; } + return filteredData; } } return data; @@ -299,13 +300,13 @@ Map /*?*/ _extractExtraData( } /// Checks that the object is a valid JSON-like data structure. -bool _validateJson(dynamic object) { +bool _validateJson(Object? object) { if (object == null || true == object || false == object) return true; if (object is num || object is String) return true; - if (object is List) { + if (object is List) { return object.every(_validateJson); } - if (object is Map) { + if (object is Map) { return object.values.every(_validateJson); } return false; diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 184b0dd04..071d548a5 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -154,7 +154,7 @@ PackageConfig parse( /// All the keys of [packageMapping] must be valid package names, /// and the values must be URIs that do not have the `package:` scheme. void write(StringSink output, PackageConfig config, - {Uri baseUri, String comment}) { + {Uri? baseUri, String? comment}) { if (baseUri != null && !baseUri.isAbsolute) { throw PackageConfigArgumentError(baseUri, "baseUri", "Must be absolute"); } @@ -187,7 +187,7 @@ void write(StringSink output, PackageConfig config, output.write(':'); // If baseUri is provided, make the URI relative to baseUri. if (baseUri != null) { - uri = relativizeUri(uri, baseUri); + uri = relativizeUri(uri, baseUri)!; } if (!uri.path.endsWith('/')) { uri = uri.replace(path: uri.path + '/'); diff --git a/pkgs/package_config/lib/src/packages_impl.dart b/pkgs/package_config/lib/src/packages_impl.dart deleted file mode 100644 index 19f103922..000000000 --- a/pkgs/package_config/lib/src/packages_impl.dart +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Implementations of [Packages] that may be used in either server or browser -/// based applications. For implementations that can only run in the browser, -/// see [package_config.packages_io_impl]. -@Deprecated("Use the package_config.json based API") -library package_config.packages_impl; - -import "dart:collection" show UnmodifiableMapView; - -import "../packages.dart"; -import "util.dart" show checkValidPackageUri; - -/// A [Packages] null-object. -class NoPackages implements Packages { - const NoPackages(); - - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - var packageName = checkValidPackageUri(packageUri, "packageUri"); - if (notFound != null) return notFound(packageUri); - throw ArgumentError.value( - packageUri, "packageUri", 'No package named "$packageName"'); - } - - Iterable get packages => Iterable.empty(); - - Map asMap() => const {}; - - String get defaultPackageName => null; - - String packageMetadata(String packageName, String key) => null; - - String libraryMetadata(Uri libraryUri, String key) => null; -} - -/// Base class for [Packages] implementations. -/// -/// This class implements the [resolve] method in terms of a private -/// member -abstract class PackagesBase implements Packages { - Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) { - packageUri = packageUri.normalizePath(); - var packageName = checkValidPackageUri(packageUri, "packageUri"); - var packageBase = getBase(packageName); - if (packageBase == null) { - if (notFound != null) return notFound(packageUri); - throw ArgumentError.value( - packageUri, "packageUri", 'No package named "$packageName"'); - } - var packagePath = packageUri.path.substring(packageName.length + 1); - return packageBase.resolve(packagePath); - } - - /// Find a base location for a package name. - /// - /// Returns `null` if no package exists with that name, and that can be - /// determined. - Uri getBase(String packageName); - - String get defaultPackageName => null; - - String packageMetadata(String packageName, String key) => null; - - String libraryMetadata(Uri libraryUri, String key) => null; -} - -/// A [Packages] implementation based on an existing map. -class MapPackages extends PackagesBase { - final Map _mapping; - MapPackages(this._mapping); - - Uri getBase(String packageName) => - packageName.isEmpty ? null : _mapping[packageName]; - - Iterable get packages => _mapping.keys; - - Map asMap() => UnmodifiableMapView(_mapping); - - String get defaultPackageName => _mapping[""]?.toString(); - - String packageMetadata(String packageName, String key) { - if (packageName.isEmpty) return null; - var uri = _mapping[packageName]; - if (uri == null || !uri.hasFragment) return null; - // This can be optimized, either by caching the map or by - // parsing incrementally instead of parsing the entire fragment. - return Uri.splitQueryString(uri.fragment)[key]; - } - - String libraryMetadata(Uri libraryUri, String key) { - if (libraryUri.isScheme("package")) { - return packageMetadata(libraryUri.pathSegments.first, key); - } - var defaultPackageNameUri = _mapping[""]; - if (defaultPackageNameUri != null) { - return packageMetadata(defaultPackageNameUri.toString(), key); - } - return null; - } -} - -/// A [Packages] implementation based on a remote (e.g., HTTP) directory. -/// -/// There is no way to detect which packages exist short of trying to use -/// them. You can't necessarily check whether a directory exists, -/// except by checking for a know file in the directory. -class NonFilePackagesDirectoryPackages extends PackagesBase { - final Uri _packageBase; - NonFilePackagesDirectoryPackages(this._packageBase); - - Uri getBase(String packageName) => _packageBase.resolve("$packageName/"); - - Error _failListingPackages() { - return UnsupportedError( - "Cannot list packages for a ${_packageBase.scheme}: " - "based package root"); - } - - Iterable get packages { - throw _failListingPackages(); - } - - Map asMap() { - throw _failListingPackages(); - } -} diff --git a/pkgs/package_config/lib/src/packages_io_impl.dart b/pkgs/package_config/lib/src/packages_io_impl.dart deleted file mode 100644 index c623f4d5d..000000000 --- a/pkgs/package_config/lib/src/packages_io_impl.dart +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2015, 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. - -/// Implementations of [Packages] that can only be used in server based -/// applications. -@Deprecated("Use the package_config.json based API") -library package_config.packages_io_impl; - -import "dart:collection" show UnmodifiableMapView; -import "dart:io" show Directory; - -import "packages_impl.dart"; - -import "util_io.dart"; - -/// A [Packages] implementation based on a local directory. -class FilePackagesDirectoryPackages extends PackagesBase { - final Directory _packageDir; - final Map _packageToBaseUriMap = {}; - - FilePackagesDirectoryPackages(this._packageDir); - - Uri getBase(String packageName) { - return _packageToBaseUriMap.putIfAbsent(packageName, () { - return Uri.file(pathJoin(_packageDir.path, packageName, '.')); - }); - } - - Iterable _listPackageNames() { - return _packageDir - .listSync() - .whereType() - .map((e) => fileName(e.path)); - } - - Iterable get packages => _listPackageNames(); - - Map asMap() { - var result = {}; - for (var packageName in _listPackageNames()) { - result[packageName] = getBase(packageName); - } - return UnmodifiableMapView(result); - } -} diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 50b140fa0..9b263ae7a 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -153,10 +153,10 @@ int firstNonWhitespaceChar(List bytes) { /// `baseUri.resolveUri(result) == uri`, /// /// The `baseUri` must be absolute. -Uri relativizeUri(Uri uri, Uri /*?*/ baseUri) { +Uri? relativizeUri(Uri? uri, Uri? baseUri) { if (baseUri == null) return uri; assert(baseUri.isAbsolute); - if (uri.hasQuery || uri.hasFragment) { + if (uri!.hasQuery || uri.hasFragment) { uri = Uri( scheme: uri.scheme, userInfo: uri.hasAuthority ? uri.userInfo : null, diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart index 2aa8c94bf..8e5f0b88e 100644 --- a/pkgs/package_config/lib/src/util_io.dart +++ b/pkgs/package_config/lib/src/util_io.dart @@ -9,7 +9,7 @@ library package_config.util_io; import 'dart:io'; import 'dart:typed_data'; -Future defaultLoader(Uri uri) async { +Future defaultLoader(Uri uri) async { if (uri.isScheme("file")) { var file = File.fromUri(uri); try { @@ -24,7 +24,7 @@ Future defaultLoader(Uri uri) async { throw UnsupportedError("Default URI unsupported scheme: $uri"); } -Future _httpGet(Uri uri) async { +Future _httpGet(Uri uri) async { assert(uri.isScheme("http") || uri.isScheme("https")); var client = HttpClient(); var request = await client.getUrl(uri); @@ -45,7 +45,7 @@ Future _httpGet(Uri uri) async { } var result = Uint8List(totalLength); var offset = 0; - for (Uint8List contentPart in splitContent) { + for (var contentPart in splitContent as Iterable) { result.setRange(offset, offset + contentPart.length, contentPart); offset += contentPart.length; } @@ -80,7 +80,7 @@ String dirName(String path) { /// /// If a part ends with a path separator, then no extra separator is /// inserted. -String pathJoin(String part1, String part2, [String part3]) { +String pathJoin(String part1, String part2, [String? part3]) { var separator = Platform.pathSeparator; var separator1 = part1.endsWith(separator) ? "" : separator; if (part3 == null) { diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index b7d596910..05c5266b2 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,20 +1,55 @@ name: package_config -version: 1.9.3 +version: 2.0.0-dev description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: - path: ^1.6.4 - charcode: ^1.1.0 + path: ^1.8.0-nullsafety.3 dev_dependencies: - test: ^1.6.4 - matcher: ^0.12.5 - pedantic: ^1.9.0 + build_resolvers: ^1.10.0 + build_runner: ^1.10.0 + build_runner_core: ^1.10.0 + build_test: ^1.3.0 + build_web_compilers: ^2.15.0 + pedantic: ^1.10.0-nullsafety.3 + test: ^1.16.0-nullsafety.4 - build_runner: ^1.0.0 - build_web_compilers: ^2.0.0 - build_test: ^0.10.0 +dependency_overrides: + analyzer: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/analyzer + build_resolvers: + git: + url: git://github.com/dart-lang/build.git + path: build_resolvers + build_runner: + git: + url: git://github.com/dart-lang/build.git + path: build_runner + build_runner_core: + git: + url: git://github.com/dart-lang/build.git + path: build_runner_core + build_test: + git: + url: git://github.com/dart-lang/build.git + path: build_test + coverage: + git: git://github.com/dart-lang/coverage.git + test: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test + test_api: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test_core diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 5cbc99214..df2374d0b 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -63,7 +63,7 @@ void main() { "package_config.json": packageConfigFile, } }, (Directory directory) async { - var config = await findPackageConfig(directory); + var config = (await findPackageConfig(directory))!; expect(config.version, 2); // Found package_config.json file. validatePackagesFile(config, directory); }); @@ -74,7 +74,7 @@ void main() { "script.dart": "main(){}", "packages": {"shouldNotBeFound": {}} }, (Directory directory) async { - var config = await findPackageConfig(directory); + var config = (await findPackageConfig(directory))!; expect(config.version, 1); // Found .packages file. validatePackagesFile(config, directory); }); @@ -89,7 +89,7 @@ void main() { "script.dart": "main(){}", } }, (Directory directory) async { - var config = await findPackageConfig(subdir(directory, "subdir/")); + var config = (await findPackageConfig(subdir(directory, "subdir/")))!; expect(config.version, 2); validatePackagesFile(config, directory); }); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 23c02d7bc..a89527918 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -61,7 +61,7 @@ void main() { "package_config.json": packageConfigFile, } }, (directory, loader) async { - var config = await findPackageConfigUri(directory, loader: loader); + var config = (await findPackageConfigUri(directory, loader: loader))!; expect(config.version, 2); // Found package_config.json file. validatePackagesFile(config, directory); }); @@ -72,7 +72,7 @@ void main() { "script.dart": "main(){}", "packages": {"shouldNotBeFound": {}} }, (directory, loader) async { - var config = await findPackageConfigUri(directory, loader: loader); + var config = (await findPackageConfigUri(directory, loader: loader))!; expect(config.version, 1); // Found .packages file. validatePackagesFile(config, directory); }); @@ -87,8 +87,8 @@ void main() { "script.dart": "main(){}", } }, (directory, loader) async { - var config = await findPackageConfigUri(directory.resolve("subdir/"), - loader: loader); + var config = (await findPackageConfigUri(directory.resolve("subdir/"), + loader: loader))!; expect(config.version, 2); validatePackagesFile(config, directory); }); diff --git a/pkgs/package_config/test/legacy/all.dart b/pkgs/package_config/test/legacy/all.dart deleted file mode 100644 index 22e2e4f9e..000000000 --- a/pkgs/package_config/test/legacy/all.dart +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2015, 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. - -@deprecated -library package_config.all_test; - -import "package:test/test.dart"; - -import "discovery_analysis_test.dart" as discovery_analysis; -import "discovery_test.dart" as discovery; -import "parse_test.dart" as parse; -import "parse_write_test.dart" as parse_write; - -void main() { - group("parse:", parse.main); - group("discovery:", discovery.main); - group("discovery-analysis:", discovery_analysis.main); - group("parse/write:", parse_write.main); -} diff --git a/pkgs/package_config/test/legacy/discovery_analysis_test.dart b/pkgs/package_config/test/legacy/discovery_analysis_test.dart deleted file mode 100644 index 7554d85d9..000000000 --- a/pkgs/package_config/test/legacy/discovery_analysis_test.dart +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2015, 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. - -@deprecated -@TestOn('vm') -library package_config.discovery_analysis_test; - -import "dart:io"; - -import "package:package_config/discovery_analysis.dart"; -import "package:package_config/packages.dart"; -import "package:path/path.dart" as path; -import "package:test/test.dart"; - -void main() { - fileTest("basic", { - ".packages": packagesFile, - "foo": {".packages": packagesFile}, - "bar": { - "packages": {"foo": {}, "bar": {}, "baz": {}} - }, - "baz": {} - }, (Directory directory) { - var dirUri = Uri.directory(directory.path); - var ctx = PackageContext.findAll(directory); - var root = ctx[directory]; - expect(root, same(ctx)); - validatePackagesFile(root.packages, dirUri); - var fooDir = sub(directory, "foo"); - var foo = ctx[fooDir]; - expect(identical(root, foo), isFalse); - validatePackagesFile(foo.packages, dirUri.resolve("foo/")); - var barDir = sub(directory, "bar"); - var bar = ctx[sub(directory, "bar")]; - validatePackagesDir(bar.packages, dirUri.resolve("bar/")); - var barbar = ctx[sub(barDir, "bar")]; - expect(barbar, same(bar)); // inherited. - var baz = ctx[sub(directory, "baz")]; - expect(baz, same(root)); // inherited. - - var map = ctx.asMap(); - expect(map.keys.map((dir) => dir.path), - unorderedEquals([directory.path, fooDir.path, barDir.path])); - return null; - }); -} - -Directory sub(Directory parent, String dirName) { - return Directory(path.join(parent.path, dirName)); -} - -const packagesFile = """ -# A comment -foo:file:///dart/packages/foo/ -bar:http://example.com/dart/packages/bar/ -baz:packages/baz/ -"""; - -void validatePackagesFile(Packages resolver, Uri location) { - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); -} - -void validatePackagesDir(Packages resolver, Uri location) { - // Expect three packages: foo, bar and baz - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - if (location.scheme == "file") { - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); - } else { - expect(() => resolver.packages, throwsUnsupportedError); - } -} - -Uri pkg(String packageName, String packagePath) { - var path; - if (packagePath.startsWith('/')) { - path = "$packageName$packagePath"; - } else { - path = "$packageName/$packagePath"; - } - return Uri(scheme: "package", path: path); -} - -/// Create a directory structure from [description] and run [fileTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void fileTest( - String name, Map description, Future fileTest(Directory directory)) { - group("file-test", () { - var tempDir = Directory.systemTemp.createTempSync("file-test"); - setUp(() { - _createFiles(tempDir, description); - }); - tearDown(() { - tempDir.deleteSync(recursive: true); - }); - test(name, () => fileTest(tempDir)); - }); -} - -void _createFiles(Directory target, Map description) { - description.forEach((name, content) { - if (content is Map) { - var subDir = Directory(path.join(target.path, name)); - subDir.createSync(); - _createFiles(subDir, content); - } else { - var file = File(path.join(target.path, name)); - file.writeAsStringSync(content, flush: true); - } - }); -} diff --git a/pkgs/package_config/test/legacy/discovery_test.dart b/pkgs/package_config/test/legacy/discovery_test.dart deleted file mode 100644 index 72874c8df..000000000 --- a/pkgs/package_config/test/legacy/discovery_test.dart +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2015, 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. - -@deprecated -@TestOn('vm') -library package_config.discovery_test; - -import "dart:async"; -import "dart:io"; -import "package:test/test.dart"; -import "package:package_config/packages.dart"; -import "package:package_config/discovery.dart"; -import "package:path/path.dart" as path; - -const packagesFile = """ -# A comment -foo:file:///dart/packages/foo/ -bar:http://example.com/dart/packages/bar/ -baz:packages/baz/ -"""; - -void validatePackagesFile(Packages resolver, Uri location) { - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("http://example.com/dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); -} - -void validatePackagesDir(Packages resolver, Uri location) { - // Expect three packages: foo, bar and baz - expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(location.resolve("packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(location.resolve("packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(location.resolve("packages/baz/qux/foo"))); - if (location.scheme == "file") { - expect(resolver.packages, unorderedEquals(["foo", "bar", "baz"])); - } else { - expect(() => resolver.packages, throwsUnsupportedError); - } -} - -Uri pkg(String packageName, String packagePath) { - var path; - if (packagePath.startsWith('/')) { - path = "$packageName$packagePath"; - } else { - path = "$packageName/$packagePath"; - } - return Uri(scheme: "package", path: path); -} - -void main() { - generalTest(".packages", { - ".packages": packagesFile, - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}} - }, (Uri location) async { - Packages resolver; - resolver = await findPackages(location); - validatePackagesFile(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesFile(resolver, location); - var specificDiscovery = (location.scheme == "file") - ? findPackagesFromFile - : findPackagesFromNonFile; - resolver = await specificDiscovery(location); - validatePackagesFile(resolver, location); - resolver = await specificDiscovery(location.resolve("script.dart")); - validatePackagesFile(resolver, location); - }); - - generalTest("packages/", { - "packages": {"foo": {}, "bar": {}, "baz": {}}, - "script.dart": "main(){}" - }, (Uri location) async { - Packages resolver; - var isFile = (location.scheme == "file"); - resolver = await findPackages(location); - validatePackagesDir(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - var specificDiscovery = - isFile ? findPackagesFromFile : findPackagesFromNonFile; - resolver = await specificDiscovery(location); - validatePackagesDir(resolver, location); - resolver = await specificDiscovery(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - }); - - generalTest("underscore packages", { - "packages": {"_foo": {}} - }, (Uri location) async { - var resolver = await findPackages(location); - expect(resolver.resolve(pkg("_foo", "foo.dart")), - equals(location.resolve("packages/_foo/foo.dart"))); - }); - - fileTest(".packages recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} - }, (Uri location) async { - Packages resolver; - resolver = await findPackages(location.resolve("subdir/")); - validatePackagesFile(resolver, location); - resolver = await findPackages(location.resolve("subdir/script.dart")); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromFile(location.resolve("subdir/")); - validatePackagesFile(resolver, location); - resolver = - await findPackagesFromFile(location.resolve("subdir/script.dart")); - validatePackagesFile(resolver, location); - }); - - httpTest(".packages not recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} - }, (Uri location) async { - Packages resolver; - var subdir = location.resolve("subdir/"); - resolver = await findPackages(subdir); - validatePackagesDir(resolver, subdir); - resolver = await findPackages(subdir.resolve("script.dart")); - validatePackagesDir(resolver, subdir); - resolver = await findPackagesFromNonFile(subdir); - validatePackagesDir(resolver, subdir); - resolver = await findPackagesFromNonFile(subdir.resolve("script.dart")); - validatePackagesDir(resolver, subdir); - }); - - fileTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { - // A file: location with no .packages or packages returns - // Packages.noPackages. - Packages resolver; - resolver = await findPackages(location); - expect(resolver, same(Packages.noPackages)); - resolver = await findPackages(location.resolve("script.dart")); - expect(resolver, same(Packages.noPackages)); - resolver = findPackagesFromFile(location); - expect(resolver, same(Packages.noPackages)); - resolver = findPackagesFromFile(location.resolve("script.dart")); - expect(resolver, same(Packages.noPackages)); - }); - - httpTest("no packages", {"script.dart": "main(){}"}, (Uri location) async { - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location); - validatePackagesDir(resolver, location); - resolver = await findPackages(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart")); - validatePackagesDir(resolver, location); - }); - - test(".packages w/ loader", () async { - var location = Uri.parse("krutch://example.com/path/"); - Future> loader(Uri file) async { - if (file.path.endsWith(".packages")) { - return packagesFile.codeUnits; - } - throw "not found"; - } - - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location, loader: loader); - validatePackagesFile(resolver, location); - resolver = - await findPackages(location.resolve("script.dart"), loader: loader); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromNonFile(location, loader: loader); - validatePackagesFile(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader: loader); - validatePackagesFile(resolver, location); - }); - - test("no packages w/ loader", () async { - var location = Uri.parse("krutch://example.com/path/"); - Future> loader(Uri file) async { - throw "not found"; - } - - // A non-file: location with no .packages or packages/: - // Assumes a packages dir exists, and resolves relative to that. - Packages resolver; - resolver = await findPackages(location, loader: loader); - validatePackagesDir(resolver, location); - resolver = - await findPackages(location.resolve("script.dart"), loader: loader); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location, loader: loader); - validatePackagesDir(resolver, location); - resolver = await findPackagesFromNonFile(location.resolve("script.dart"), - loader: loader); - validatePackagesDir(resolver, location); - }); - - generalTest("loadPackagesFile", {".packages": packagesFile}, - (Uri directory) async { - var file = directory.resolve(".packages"); - var resolver = await loadPackagesFile(file); - validatePackagesFile(resolver, file); - }); - - generalTest( - "loadPackagesFile non-default name", {"pheldagriff": packagesFile}, - (Uri directory) async { - var file = directory.resolve("pheldagriff"); - var resolver = await loadPackagesFile(file); - validatePackagesFile(resolver, file); - }); - - test("loadPackagesFile w/ loader", () async { - Future> loader(Uri uri) async => packagesFile.codeUnits; - var file = Uri.parse("krutz://example.com/.packages"); - var resolver = await loadPackagesFile(file, loader: loader); - validatePackagesFile(resolver, file); - }); - - generalTest("loadPackagesFile not found", {}, (Uri directory) async { - var file = directory.resolve(".packages"); - expect( - loadPackagesFile(file), - throwsA(anyOf( - TypeMatcher(), TypeMatcher()))); - }); - - generalTest("loadPackagesFile syntax error", {".packages": "syntax error"}, - (Uri directory) async { - var file = directory.resolve(".packages"); - expect(loadPackagesFile(file), throwsFormatException); - }); - - generalTest("getPackagesDir", { - "packages": {"foo": {}, "bar": {}, "baz": {}} - }, (Uri directory) async { - var packages = directory.resolve("packages/"); - var resolver = getPackagesDirectory(packages); - var resolved = resolver.resolve(pkg("foo", "flip/flop")); - expect(resolved, packages.resolve("foo/flip/flop")); - }); -} - -/// Create a directory structure from [description] and run [fileTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void fileTest(String name, Map description, Future fileTest(Uri directory)) { - group("file-test", () { - var tempDir = Directory.systemTemp.createTempSync("file-test"); - setUp(() { - _createFiles(tempDir, description); - }); - tearDown(() { - tempDir.deleteSync(recursive: true); - }); - test(name, () => fileTest(Uri.file(path.join(tempDir.path, ".")))); - }); -} - -/// HTTP-server the directory structure from [description] and run [htpTest]. -/// -/// Description is a map, each key is a file entry. If the value is a map, -/// it's a sub-dir, otherwise it's a file and the value is the content -/// as a string. -void httpTest(String name, Map description, Future httpTest(Uri directory)) { - group("http-test", () { - var serverSub; - var uri; - setUp(() { - return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) { - uri = Uri( - scheme: "http", host: "127.0.0.1", port: server.port, path: "/"); - serverSub = server.listen((HttpRequest request) { - // No error handling. - var path = request.uri.path; - if (path.startsWith('/')) path = path.substring(1); - if (path.endsWith('/')) path = path.substring(0, path.length - 1); - var parts = path.split('/'); - dynamic fileOrDir = description; - for (var i = 0; i < parts.length; i++) { - fileOrDir = fileOrDir[parts[i]]; - if (fileOrDir == null) { - request.response.statusCode = 404; - request.response.close(); - return; - } - } - request.response.write(fileOrDir); - request.response.close(); - }); - }); - }); - tearDown(() => serverSub.cancel()); - test(name, () => httpTest(uri)); - }); -} - -void generalTest(String name, Map description, Future action(Uri location)) { - fileTest(name, description, action); - httpTest(name, description, action); -} - -void _createFiles(Directory target, Map description) { - description.forEach((name, content) { - if (content is Map) { - var subDir = Directory(path.join(target.path, name)); - subDir.createSync(); - _createFiles(subDir, content); - } else { - var file = File(path.join(target.path, name)); - file.writeAsStringSync(content, flush: true); - } - }); -} diff --git a/pkgs/package_config/test/legacy/parse_test.dart b/pkgs/package_config/test/legacy/parse_test.dart deleted file mode 100644 index b9cf1f8fd..000000000 --- a/pkgs/package_config/test/legacy/parse_test.dart +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright (c) 2015, 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. - -@deprecated -library package_config.parse_test; - -import "package:package_config/packages.dart"; -import "package:package_config/packages_file.dart" show parse; -import "package:package_config/src/packages_impl.dart"; -import "package:test/test.dart"; - -void main() { - var base = Uri.parse("file:///one/two/three/packages.map"); - test("empty", () { - var packages = doParse(emptySample, base); - expect(packages.asMap(), isEmpty); - }); - test("comment only", () { - var packages = doParse(commentOnlySample, base); - expect(packages.asMap(), isEmpty); - }); - test("empty lines only", () { - var packages = doParse(emptyLinesSample, base); - expect(packages.asMap(), isEmpty); - }); - - test("empty lines only", () { - var packages = doParse(emptyLinesSample, base); - expect(packages.asMap(), isEmpty); - }); - - test("single", () { - var packages = doParse(singleRelativeSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single no slash", () { - var packages = doParse(singleRelativeSampleNoSlash, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single no newline", () { - var packages = doParse(singleRelativeSampleNoNewline, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("single absolute authority", () { - var packages = doParse(singleAbsoluteSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(Uri.parse("http://example.com/some/where/bar/baz.dart"))); - }); - - test("single empty path", () { - var packages = doParse(singleEmptyPathSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.replace(path: "${base.path}/bar/baz.dart"))); - }); - - test("single absolute path", () { - var packages = doParse(singleAbsolutePathSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.replace(path: "/test/bar/baz.dart"))); - }); - - test("multiple", () { - var packages = doParse(multiRelativeSample, base); - expect(packages.packages.toList()..sort(), equals(["bar", "foo"])); - expect(packages.resolve(Uri.parse("package:foo/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - expect(packages.resolve(Uri.parse("package:bar/foo/baz.dart")), - equals(base.resolve("../test2/").resolve("foo/baz.dart"))); - }); - - test("dot-dot 1", () { - var packages = doParse(singleRelativeSample, base); - expect(packages.packages.toList(), equals(["foo"])); - expect(packages.resolve(Uri.parse("package:foo/qux/../bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("all valid chars can be used in URI segment", () { - var packages = doParse(allValidCharsSample, base); - expect(packages.packages.toList(), equals([allValidChars])); - expect(packages.resolve(Uri.parse("package:$allValidChars/bar/baz.dart")), - equals(base.resolve("../test/").resolve("bar/baz.dart"))); - }); - - test("no invalid chars accepted", () { - var map = {}; - for (var i = 0; i < allValidChars.length; i++) { - map[allValidChars.codeUnitAt(i)] = true; - } - for (var i = 0; i <= 255; i++) { - if (map[i] == true) continue; - var char = String.fromCharCode(i); - expect(() => doParse("x${char}x:x", null), - anyOf(throwsNoSuchMethodError, throwsFormatException)); - } - }); - - test("no escapes", () { - expect(() => doParse("x%41x:x", base), throwsFormatException); - }); - - test("same name twice", () { - expect( - () => doParse(singleRelativeSample * 2, base), throwsFormatException); - }); - - test("disallow default package", () { - expect(() => doParse(":foo", base, allowDefaultPackage: false), - throwsFormatException); - }); - - test("allow default package", () { - var packages = doParse(":foo", base, allowDefaultPackage: true); - expect(packages.defaultPackageName, "foo"); - }); - - test("allow default package name with dot", () { - var packages = doParse(":foo.bar", base, allowDefaultPackage: true); - expect(packages.defaultPackageName, "foo.bar"); - }); - - test("not two default packages", () { - expect(() => doParse(":foo\n:bar", base, allowDefaultPackage: true), - throwsFormatException); - }); - - test("default package invalid package name", () { - // Not a valid *package name*. - expect(() => doParse(":foo/bar", base, allowDefaultPackage: true), - throwsFormatException); - }); - - group("metadata", () { - var packages = doParse( - ":foo\n" - "foo:foo#metafoo=1\n" - "bar:bar#metabar=2\n" - "baz:baz\n" - "qux:qux#metaqux1=3&metaqux2=4\n", - base, - allowDefaultPackage: true); - test("non-existing", () { - // non-package name. - expect(packages.packageMetadata("///", "f"), null); - expect(packages.packageMetadata("", "f"), null); - // unconfigured package name. - expect(packages.packageMetadata("absent", "f"), null); - // package name without that metadata - expect(packages.packageMetadata("foo", "notfoo"), null); - }); - test("lookup", () { - expect(packages.packageMetadata("foo", "metafoo"), "1"); - expect(packages.packageMetadata("bar", "metabar"), "2"); - expect(packages.packageMetadata("qux", "metaqux1"), "3"); - expect(packages.packageMetadata("qux", "metaqux2"), "4"); - }); - test("by library URI", () { - expect( - packages.libraryMetadata( - Uri.parse("package:foo/index.dart"), "metafoo"), - "1"); - expect( - packages.libraryMetadata( - Uri.parse("package:bar/index.dart"), "metabar"), - "2"); - expect( - packages.libraryMetadata( - Uri.parse("package:qux/index.dart"), "metaqux1"), - "3"); - expect( - packages.libraryMetadata( - Uri.parse("package:qux/index.dart"), "metaqux2"), - "4"); - }); - test("by default package", () { - expect( - packages.libraryMetadata( - Uri.parse("file:///whatever.dart"), "metafoo"), - "1"); - }); - }); - - for (var invalidSample in invalid) { - test("invalid '$invalidSample'", () { - var result; - try { - result = doParse(invalidSample, base); - } on FormatException { - // expected - return; - } - fail("Resolved to $result"); - }); - } -} - -Packages doParse(String sample, Uri baseUri, - {bool allowDefaultPackage = false}) { - var map = parse(sample.codeUnits, baseUri, - allowDefaultPackage: allowDefaultPackage); - return MapPackages(map); -} - -// Valid samples. -var emptySample = ""; -var commentOnlySample = "# comment only\n"; -var emptyLinesSample = "\n\n\r\n"; -var singleRelativeSample = "foo:../test/\n"; -var singleRelativeSampleNoSlash = "foo:../test\n"; -var singleRelativeSampleNoNewline = "foo:../test/"; -var singleAbsoluteSample = "foo:http://example.com/some/where/\n"; -var singleEmptyPathSample = "foo:\n"; -var singleAbsolutePathSample = "foo:/test/\n"; -var multiRelativeSample = "foo:../test/\nbar:../test2/\n"; -// All valid path segment characters in an URI. -var allValidChars = r"!$&'()*+,-.0123456789;=" - r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; - -var allValidCharsSample = "${allValidChars}:../test/\n"; - -// Invalid samples. -var invalid = [ - ":baz.dart", // empty. - "foobar=baz.dart", // no colon (but an equals, which is not the same) - ".:../test/", // dot segment - "..:../test/", // dot-dot segment - "...:../test/", // dot-dot-dot segment - "foo/bar:../test/", // slash in name - "/foo:../test/", // slash at start of name - "?:../test/", // invalid characters. - "[:../test/", // invalid characters. - "x#:../test/", // invalid characters. -]; diff --git a/pkgs/package_config/test/legacy/parse_write_test.dart b/pkgs/package_config/test/legacy/parse_write_test.dart deleted file mode 100644 index a51ced1ba..000000000 --- a/pkgs/package_config/test/legacy/parse_write_test.dart +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2015, 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. - -@deprecated -library package_config.parse_write_test; - -import "dart:convert" show utf8; -import "package:package_config/packages_file.dart"; -import "package:test/test.dart"; - -void main() { - void testBase(baseDirString) { - var baseDir = Uri.parse(baseDirString); - group("${baseDir.scheme} base", () { - var packagesFile = baseDir.resolve(".packages"); - - void roundTripTest(String name, Map map) { - group(name, () { - test("write with no baseUri", () { - var content = writeToString(map).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with base directory", () { - var content = writeToString(map, baseUri: baseDir).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with base .packages file", () { - var content = writeToString(map, baseUri: packagesFile).codeUnits; - var resultMap = parse(content, packagesFile); - expect(resultMap, map); - }); - - test("write with defaultPackageName", () { - var content = writeToString( - {'': Uri.parse('my_pkg')}..addAll(map), - allowDefaultPackage: true, - ).codeUnits; - var resultMap = parse( - content, - packagesFile, - allowDefaultPackage: true, - ); - expect(resultMap[''].toString(), 'my_pkg'); - expect( - resultMap, - {'': Uri.parse('my_pkg')}..addAll(map), - ); - }); - - test("write with defaultPackageName (utf8)", () { - var content = utf8.encode(writeToString( - {'': Uri.parse('my_pkg')}..addAll(map), - allowDefaultPackage: true, - )); - var resultMap = parse( - content, - packagesFile, - allowDefaultPackage: true, - ); - expect(resultMap[''].toString(), 'my_pkg'); - expect( - resultMap, - {'': Uri.parse('my_pkg')}..addAll(map), - ); - }); - }); - } - - var lowerDir = baseDir.resolve("path3/path4/"); - var higherDir = baseDir.resolve("../"); - var parallelDir = baseDir.resolve("../path3/"); - var rootDir = baseDir.resolve("/"); - var fileDir = Uri.parse("file:///path1/part2/"); - var httpDir = Uri.parse("http://example.com/path1/path2/"); - var otherDir = Uri.parse("other:/path1/path2/"); - - roundTripTest("empty", {}); - roundTripTest("lower directory", {"foo": lowerDir}); - roundTripTest("higher directory", {"foo": higherDir}); - roundTripTest("parallel directory", {"foo": parallelDir}); - roundTripTest("same directory", {"foo": baseDir}); - roundTripTest("root directory", {"foo": rootDir}); - roundTripTest("file directory", {"foo": fileDir}); - roundTripTest("http directory", {"foo": httpDir}); - roundTripTest("other scheme directory", {"foo": otherDir}); - roundTripTest("multiple same-type directories", - {"foo": lowerDir, "bar": higherDir, "baz": parallelDir}); - roundTripTest("multiple scheme directories", - {"foo": fileDir, "bar": httpDir, "baz": otherDir}); - roundTripTest("multiple scheme directories and mutliple same type", { - "foo": fileDir, - "bar": httpDir, - "baz": otherDir, - "qux": lowerDir, - "hip": higherDir, - "dep": parallelDir - }); - }); - } - - testBase("file:///base1/base2/"); - testBase("http://example.com/base1/base2/"); - testBase("other:/base1/base2/"); - - // Check that writing adds the comment. - test("write preserves comment", () { - var comment = "comment line 1\ncomment line 2\ncomment line 3"; - var result = writeToString({}, comment: comment); - // Comment with "# " before each line and "\n" after last. - var expectedComment = - "# comment line 1\n# comment line 2\n# comment line 3\n"; - expect(result, startsWith(expectedComment)); - }); -} - -String writeToString( - Map map, { - Uri baseUri, - String comment, - bool allowDefaultPackage = false, -}) { - var buffer = StringBuffer(); - write(buffer, map, - baseUri: baseUri, - comment: comment, - allowDefaultPackage: allowDefaultPackage); - return buffer.toString(); -} diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 59a7e7126..385be368e 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -32,7 +32,7 @@ void main() { expect(result.resolve(pkg("baz", "baz.dart")), Uri.parse("file:///tmp/lib/baz.dart")); - var foo = result["foo"]; + var foo = result["foo"]!; expect(foo, isNotNull); expect(foo.root, Uri.parse("file:///foo/")); expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); @@ -111,8 +111,10 @@ void main() { "other": [42] } """; - var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), - Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); + var config = parsePackageConfigBytes( + utf8.encode(packageConfigFile) as Uint8List, + Uri.parse("file:///tmp/.dart_tool/file.dart"), + throwError); expect(config.version, 2); expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz", "noslash"}); @@ -124,28 +126,28 @@ void main() { expect(config.resolve(pkg("baz", "baz.dart")), Uri.parse("file:///tmp/lib/baz.dart")); - var foo = config["foo"]; + var foo = config["foo"]!; expect(foo, isNotNull); expect(foo.root, Uri.parse("file:///foo/")); expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); expect(foo.languageVersion, LanguageVersion(2, 5)); expect(foo.extraData, {"nonstandard": true}); - var bar = config["bar"]; + var bar = config["bar"]!; expect(bar, isNotNull); expect(bar.root, Uri.parse("file:///bar/")); expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/")); expect(bar.languageVersion, LanguageVersion(9999, 9999)); expect(bar.extraData, null); - var baz = config["baz"]; + var baz = config["baz"]!; expect(baz, isNotNull); expect(baz.root, Uri.parse("file:///tmp/")); expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/")); expect(baz.languageVersion, null); // No slash after root or package root. One is inserted. - var noslash = config["noslash"]; + var noslash = config["noslash"]!; expect(noslash, isNotNull); expect(noslash.root, Uri.parse("file:///tmp/noslash/")); expect(noslash.packageUriRoot, Uri.parse("file:///tmp/noslash/lib/")); @@ -185,8 +187,10 @@ void main() { "configVersion": 2 } """; - var config = parsePackageConfigBytes(utf8.encode(packageConfigFile), - Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); + var config = parsePackageConfigBytes( + utf8.encode(packageConfigFile) as Uint8List, + Uri.parse("file:///tmp/.dart_tool/file.dart"), + throwError); expect(config.version, 2); expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); @@ -209,8 +213,10 @@ void main() { var name = '"name":"foo"'; var root = '"rootUri":"/foo/"'; test("minimal", () { - var config = parsePackageConfigBytes(utf8.encode("{$cfg,$pkgs}"), - Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); + var config = parsePackageConfigBytes( + utf8.encode("{$cfg,$pkgs}") as Uint8List, + Uri.parse("file:///tmp/.dart_tool/file.dart"), + throwError); expect(config.version, 2); expect(config.packages, isEmpty); }); @@ -218,7 +224,7 @@ void main() { // A package must have a name and a rootUri, the remaining properties // are optional. var config = parsePackageConfigBytes( - utf8.encode('{$cfg,"packages":[{$name,$root}]}'), + utf8.encode('{$cfg,"packages":[{$name,$root}]}') as Uint8List, Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); @@ -235,17 +241,17 @@ void main() { {"name": "qux", "rootUri": "/foo/qux/", "packageUri": "lib/"}, ] })); - var config = parsePackageConfigBytes(configBytes, + var config = parsePackageConfigBytes(configBytes as Uint8List, Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); expect(config.version, 2); - expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart")).name, + expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart"))!.name, "foo"); - expect( - config.packageOf(Uri.parse("file:///foo/bar/lala.dart")).name, "bar"); - expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart")).name, + expect(config.packageOf(Uri.parse("file:///foo/bar/lala.dart"))!.name, + "bar"); + expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart"))!.name, "baz"); - expect( - config.packageOf(Uri.parse("file:///foo/qux/lala.dart")).name, "qux"); + expect(config.packageOf(Uri.parse("file:///foo/qux/lala.dart"))!.name, + "qux"); expect(config.toPackageUri(Uri.parse("file:///foo/lib/diz")), Uri.parse("package:foo/diz")); expect(config.toPackageUri(Uri.parse("file:///foo/bar/lib/diz")), @@ -260,7 +266,7 @@ void main() { void testThrows(String name, String source) { test(name, () { expect( - () => parsePackageConfigBytes(utf8.encode(source), + () => parsePackageConfigBytes(utf8.encode(source) as Uint8List, Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError), throwsA(TypeMatcher())); }); @@ -386,7 +392,7 @@ void main() { for (var package in config.packages) { var name = package.name; test("package $name", () { - var expectedPackage = expected[name]; + var expectedPackage = expected[name]!; expect(expectedPackage, isNotNull); expect(package.root, expectedPackage.root, reason: "root"); expect(package.packageUriRoot, expectedPackage.packageUriRoot, diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 6e689b734..2b262e1b2 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -34,18 +34,18 @@ ${packages.map((nu) => """ /// it's a subdirectory, otherwise it's a file and the value is the content /// as a string. void loaderTest(String name, Map description, - void loaderTest(Uri root, Future loader(Uri uri))) { + void loaderTest(Uri root, Future loader(Uri uri))) { var root = Uri(scheme: "test", path: "/"); - Future loader(Uri uri) async { + Future loader(Uri uri) async { var path = uri.path; if (!uri.isScheme("test") || !path.startsWith("/")) return null; var parts = path.split("/"); - dynamic value = description; + Object? value = description; for (var i = 1; i < parts.length; i++) { - if (value is! Map) return null; + if (value is! Map) return null; value = value[parts[i]]; } - if (value is String) return utf8.encode(value); + if (value is String) return utf8.encode(value) as Uint8List; return null; } diff --git a/pkgs/package_config/test/src/util_io.dart b/pkgs/package_config/test/src/util_io.dart index d05618a07..37deee9e1 100644 --- a/pkgs/package_config/test/src/util_io.dart +++ b/pkgs/package_config/test/src/util_io.dart @@ -35,20 +35,20 @@ void fileTest(String name, Map description, /// with the content as description. /// Otherwise the content should be a string, /// which is written to the file as UTF-8. -Directory createTestFiles(Map description) { - var target = Directory.systemTemp.createTempSync("pkgcfgtest"); - _createFiles(target, description); - return target; -} +// Directory createTestFiles(Map description) { +// var target = Directory.systemTemp.createTempSync("pkgcfgtest"); +// _createFiles(target, description); +// return target; +// } // Creates temporary files in the target directory. -void _createFiles(Directory target, Map description) { +void _createFiles(Directory target, Map description) { description.forEach((name, content) { var entryName = pathJoin(target.path, "$name"); - if (content is Map) { + if (content is Map) { _createFiles(Directory(entryName)..createSync(), content); } else { - File(entryName).writeAsStringSync(content, flush: true); + File(entryName).writeAsStringSync(content as String, flush: true); } }); } From 3a99a4ecbc2cd0508ff20b1e1b56a5397d83da67 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Mon, 7 Dec 2020 13:32:36 -0800 Subject: [PATCH 162/281] migrate from `dartanalyzer` to `dart analyze` the experiment is no longer required and warnings are fatal by default --- pkgs/pool/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml index 87be92616..431bd27e0 100644 --- a/pkgs/pool/.travis.yml +++ b/pkgs/pool/.travis.yml @@ -8,7 +8,7 @@ jobs: - stage: analyze_and_format name: "Analyze" os: linux - script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + script: dart analyze --fatal-infos . - stage: analyze_and_format name: "Format" os: linux From ba5cc8d21bdbeccffa9327d0287511b430767433 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 9 Dec 2020 15:06:53 -0800 Subject: [PATCH 163/281] Add override for _fe_analyzer_shared (dart-lang/package_config#96) We currently need the dependency overrides because of the circular dev_dependencies and the major version change. It is still safe to publish since no normal dependencies are overridden. The dependency overrides are causing us to pull in incompatible versions of `analyzer` and `_fe_analyzer_shared` since there was a breaking change in the latter. Pulling it in from the SDK should cause both to be compatible until we can drop the overrides entirely. --- pkgs/package_config/pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 05c5266b2..48b8d3c95 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -19,6 +19,10 @@ dev_dependencies: test: ^1.16.0-nullsafety.4 dependency_overrides: + _fe_analyzer_shared: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/_fe_analyzer_shared analyzer: git: url: git://github.com/dart-lang/sdk.git From 02e6eb5c0c6e6f1e295377caa56d06ad8689a5d2 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 10 Dec 2020 10:41:31 -0800 Subject: [PATCH 164/281] migrate to `dart analyze` (warnings are now fatal by default) --- pkgs/package_config/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml index 3a47bb586..c4e5bdb8f 100644 --- a/pkgs/package_config/.travis.yml +++ b/pkgs/package_config/.travis.yml @@ -5,7 +5,7 @@ dart: dart_task: - test - dartfmt - - dartanalyzer: --fatal-warnings --fatal-infos . + - dart analyze --fatal-infos . matrix: include: From c9395552ff2def38ea8e858560c766185522c6ce Mon Sep 17 00:00:00 2001 From: Lasse Reichstein Holst Nielsen Date: Tue, 19 Jan 2021 15:00:16 +0100 Subject: [PATCH 165/281] Change version to 2.0.0-nullsafety.0 for consistency. --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 48b8d3c95..c1cfd9456 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.0-dev +version: 2.0.0-nullsafety.0 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config From 846247817732cdab8bf5f02a83d42a6913e0b52a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 21 Jan 2021 00:19:08 -0800 Subject: [PATCH 166/281] Migrate to GitHub Actions (dart-lang/pool#51) --- pkgs/pool/.github/workflows/ci.yml | 64 ++++++++++++++++++++++++++++++ pkgs/pool/.travis.yml | 35 ---------------- 2 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 pkgs/pool/.github/workflows/ci.yml delete mode 100644 pkgs/pool/.travis.yml diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml new file mode 100644 index 000000000..f55a818da --- /dev/null +++ b/pkgs/pool/.github/workflows/ci.yml @@ -0,0 +1,64 @@ +name: CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/pool/.travis.yml b/pkgs/pool/.travis.yml deleted file mode 100644 index 431bd27e0..000000000 --- a/pkgs/pool/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -language: dart - -dart: - - dev - -jobs: - include: - - stage: analyze_and_format - name: "Analyze" - os: linux - script: dart analyze --fatal-infos . - - stage: analyze_and_format - name: "Format" - os: linux - script: dartfmt -n --set-exit-if-changed . - - stage: test - name: "Vm Tests" - os: linux - script: pub run --enable-experiment=non-nullable test -p vm - - stage: test - name: "Web Tests" - os: linux - script: pub run --enable-experiment=non-nullable test -p chrome - -stages: - - analyze_and_format - - test - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 43d80949f6710a34c66df5a4c34247e4079ae03c Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 21 Jan 2021 16:32:45 +0100 Subject: [PATCH 167/281] Make it possible to control whether the `rootUri` path is relativized. (dart-lang/package_config#102) * Make it possible to control whether the `rootUri` path is relativized. Adds `relativeRoot` boolean to `PackageConfig` which does nothing except to control whether the `root` URI is made relative to the configuration file when written to a configuration file. The parsers remember whether the root URI was relative originally. Also fixes bad cast. --- pkgs/package_config/CHANGELOG.md | 2 + .../lib/src/package_config.dart | 19 ++++++-- .../lib/src/package_config_impl.dart | 9 ++-- .../lib/src/package_config_json.dart | 19 +++++--- .../package_config/lib/src/packages_file.dart | 8 ++-- pkgs/package_config/lib/src/util.dart | 15 ++++++ pkgs/package_config/pubspec.yaml | 2 +- .../test/package_config_impl_test.dart | 47 ++++++++++++++++++- pkgs/package_config/test/parse_test.dart | 5 ++ 9 files changed, 107 insertions(+), 19 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 32ff3f17f..4a04782b4 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -2,6 +2,8 @@ - Migrate to null safety. - Remove legacy APIs. +- Adds `relativeRoot` property to `Package` which controls whether to + make the root URI relative when writing a configuration file. ## 1.9.3 diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 63d01eacd..26aa39622 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -224,14 +224,20 @@ abstract class Package { /// version, which means two decimal integer literals separated by a `.`, /// where the integer literals have no leading zeros unless they are /// a single zero digit. + /// + /// The [relativeRoot] controls whether the [root] is written as + /// relative to the `package_config.json` file when the package + /// configuration is written to a file. It defaults to being relative. + /// /// If [extraData] is supplied, it will be available as the /// [Package.extraData] of the created package. factory Package(String name, Uri root, {Uri? packageUriRoot, LanguageVersion? languageVersion, - Object? extraData}) => - SimplePackage.validate( - name, root, packageUriRoot, languageVersion, extraData, throwError)!; + Object? extraData, + bool relativeRoot = true}) => + SimplePackage.validate(name, root, packageUriRoot, languageVersion, + extraData, relativeRoot, throwError)!; /// The package-name of the package. String get name; @@ -275,6 +281,13 @@ abstract class Package { /// The standard `package_config.json` file storage will only store /// JSON-like list/map data structures. Object? get extraData; + + /// Whether the [root] URI should be written as relative. + /// + /// When the configuration is written to a `package_config.json` + /// file, the [root] URI can be either relative to the file + /// location or absolute, controller by this value. + bool get relativeRoot; } /// A language version. diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 5c6b7f728..c75111580 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -61,7 +61,8 @@ class SimplePackageConfig implements PackageConfig { originalPackage.root, originalPackage.packageUriRoot, originalPackage.languageVersion, - originalPackage.extraData, (error) { + originalPackage.extraData, + originalPackage.relativeRoot, (error) { if (error is PackageConfigArgumentError) { onError(PackageConfigArgumentError(packages, "packages", "Package ${package!.name}: ${error.message}")); @@ -159,9 +160,10 @@ class SimplePackage implements Package { final Uri packageUriRoot; final LanguageVersion? languageVersion; final Object? extraData; + final bool relativeRoot; SimplePackage._(this.name, this.root, this.packageUriRoot, - this.languageVersion, this.extraData); + this.languageVersion, this.extraData, this.relativeRoot); /// Creates a [SimplePackage] with the provided content. /// @@ -184,6 +186,7 @@ class SimplePackage implements Package { Uri? packageUriRoot, LanguageVersion? languageVersion, Object? extraData, + bool relativeRoot, void onError(Object error)) { var fatalError = false; var invalidIndex = checkPackageName(name); @@ -229,7 +232,7 @@ class SimplePackage implements Package { } if (fatalError) return null; return SimplePackage._( - name, root, packageUriRoot, languageVersion, extraData); + name, root, packageUriRoot, languageVersion, extraData, relativeRoot); } } diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 25b04c4d1..979c35ed4 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -146,7 +146,9 @@ PackageConfig parsePackageConfigJson( onError(PackageConfigFormatException("Missing rootUri entry", entry)); } if (name == null || rootUri == null) return null; - var root = baseLocation.resolve(rootUri!); + var parsedRootUri = Uri.parse(rootUri!); + var relativeRoot = !hasAbsolutePath(parsedRootUri); + var root = baseLocation.resolveUri(parsedRootUri); if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/"); var packageRoot = root; if (packageUri != null) packageRoot = root.resolve(packageUri!); @@ -161,8 +163,8 @@ PackageConfig parsePackageConfigJson( version = SimpleInvalidLanguageVersion("invalid"); } - return SimplePackage.validate(name!, root, packageRoot, version, extraData, - (error) { + return SimplePackage.validate( + name!, root, packageRoot, version, extraData, relativeRoot, (error) { if (error is ArgumentError) { onError( PackageConfigFormatException(error.message, error.invalidValue)); @@ -232,7 +234,7 @@ void writePackageConfigJsonString( PackageConfig config, Uri? baseUri, StringSink output) { // Can be optimized. var data = packageConfigToJson(config, baseUri); - output.write(JsonEncoder.withIndent(" ").convert(data) as Uint8List); + output.write(JsonEncoder.withIndent(" ").convert(data)); } Map packageConfigToJson(PackageConfig config, Uri? baseUri) => @@ -243,11 +245,14 @@ Map packageConfigToJson(PackageConfig config, Uri? baseUri) => for (var package in config.packages) { _nameKey: package.name, - _rootUriKey: relativizeUri(package.root, baseUri).toString(), + _rootUriKey: trailingSlash((package.relativeRoot + ? relativizeUri(package.root, baseUri) + : package.root) + .toString()), if (package.root != package.packageUriRoot) - _packageUriKey: + _packageUriKey: trailingSlash( relativizeUri(package.packageUriRoot, package.root) - .toString(), + .toString()), if (package.languageVersion != null && package.languageVersion is! InvalidLanguageVersion) _languageVersionKey: package.languageVersion.toString(), diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 071d548a5..ddcf8563b 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -96,11 +96,13 @@ PackageConfig parse( var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); Uri packageLocation; try { - packageLocation = baseLocation.resolve(packageValue); + packageLocation = Uri.parse(packageValue); } on FormatException catch (e) { onError(PackageConfigFormatException.from(e)); continue; } + var relativeRoot = !hasAbsolutePath(packageLocation); + packageLocation = baseLocation.resolveUri(packageLocation); if (packageLocation.isScheme("package")) { onError(PackageConfigFormatException( "Package URI as location for package", source, separatorIndex + 1)); @@ -122,8 +124,8 @@ PackageConfig parse( rootUri = packageLocation.replace(path: path.substring(0, path.length - 4)); } - var package = SimplePackage.validate( - packageName, rootUri, packageLocation, _languageVersion, null, (error) { + var package = SimplePackage.validate(packageName, rootUri, packageLocation, + _languageVersion, null, relativeRoot, (error) { if (error is ArgumentError) { onError(PackageConfigFormatException(error.message, source)); } else { diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 9b263ae7a..f490cdc1c 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -137,6 +137,21 @@ int firstNonWhitespaceChar(List bytes) { return -1; } +/// Appends a trailing `/` if the path doesn't end with one. +String trailingSlash(String path) { + if (path.isEmpty || path.endsWith("/")) return path; + return path + "/"; +} + +/// Whether a URI should not be considered relative to the base URI. +/// +/// Used to determine whether a parsed root URI is relative +/// to the configuration file or not. +/// If it is relative, then it's rewritten as relative when +/// output again later. If not, it's output as absolute. +bool hasAbsolutePath(Uri uri) => + uri.hasScheme || uri.hasAuthority || uri.hasAbsolutePath; + /// Attempts to return a relative path-only URI for [uri]. /// /// First removes any query or fragment part from [uri]. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index c1cfd9456..5903bc8ac 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.0-nullsafety.0 +version: 2.0.0-nullsafety.1 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart index 6921118f3..bb00d1210 100644 --- a/pkgs/package_config/test/package_config_impl_test.dart +++ b/pkgs/package_config/test/package_config_impl_test.dart @@ -2,6 +2,8 @@ // 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. +import "dart:convert" show jsonDecode; + import "package:package_config/package_config_types.dart"; import "package:test/test.dart"; import "src/util.dart"; @@ -72,6 +74,7 @@ void main() { var absolute = root.resolve("foo/bar/"); var package = Package("name", root, packageUriRoot: absolute, + relativeRoot: false, languageVersion: version, extraData: unique); expect(package.name, "name"); @@ -79,16 +82,18 @@ void main() { expect(package.packageUriRoot, absolute); expect(package.languageVersion, version); expect(package.extraData, same(unique)); + expect(package.relativeRoot, false); }); test("relative package root", () { var relative = Uri.parse("foo/bar/"); var absolute = root.resolveUri(relative); - var package = - Package("name", root, packageUriRoot: relative, extraData: unique); + var package = Package("name", root, + packageUriRoot: relative, relativeRoot: true, extraData: unique); expect(package.name, "name"); expect(package.root, root); expect(package.packageUriRoot, absolute); + expect(package.relativeRoot, true); expect(package.languageVersion, null); expect(package.extraData, same(unique)); }); @@ -140,6 +145,44 @@ void main() { expect(resolved, root.resolve("a/b")); }); }); + test("writeString", () { + var config = PackageConfig([ + Package("foo", Uri.parse("file:///pkg/foo/"), + packageUriRoot: Uri.parse("file:///pkg/foo/lib/"), + relativeRoot: false, + languageVersion: LanguageVersion(2, 4), + extraData: {"foo": "foo!"}), + Package("bar", Uri.parse("file:///pkg/bar/"), + packageUriRoot: Uri.parse("file:///pkg/bar/lib/"), + relativeRoot: true, + extraData: {"bar": "bar!"}), + ], extraData: { + "extra": "data" + }); + var buffer = StringBuffer(); + PackageConfig.writeString(config, buffer, Uri.parse("file:///pkg/")); + var text = buffer.toString(); + var json = jsonDecode(text); // Is valid JSON. + expect(json, { + "configVersion": 2, + "packages": unorderedEquals([ + { + "name": "foo", + "rootUri": "file:///pkg/foo/", + "packageUri": "lib/", + "languageVersion": "2.4", + "foo": "foo!", + }, + { + "name": "bar", + "rootUri": "bar/", + "packageUri": "lib/", + "bar": "bar!", + }, + ]), + "extra": "data", + }); + }); } final Matcher throwsPackageConfigError = throwsA(isA()); diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 385be368e..ef73c2e1e 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -37,6 +37,7 @@ void main() { expect(foo.root, Uri.parse("file:///foo/")); expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); expect(foo.languageVersion, LanguageVersion(2, 7)); + expect(foo.relativeRoot, false); }); test("valid empty", () { @@ -132,6 +133,7 @@ void main() { expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); expect(foo.languageVersion, LanguageVersion(2, 5)); expect(foo.extraData, {"nonstandard": true}); + expect(foo.relativeRoot, false); var bar = config["bar"]!; expect(bar, isNotNull); @@ -139,12 +141,14 @@ void main() { expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/")); expect(bar.languageVersion, LanguageVersion(9999, 9999)); expect(bar.extraData, null); + expect(bar.relativeRoot, false); var baz = config["baz"]!; expect(baz, isNotNull); expect(baz.root, Uri.parse("file:///tmp/")); expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/")); expect(baz.languageVersion, null); + expect(baz.relativeRoot, true); // No slash after root or package root. One is inserted. var noslash = config["noslash"]!; @@ -152,6 +156,7 @@ void main() { expect(noslash.root, Uri.parse("file:///tmp/noslash/")); expect(noslash.packageUriRoot, Uri.parse("file:///tmp/noslash/lib/")); expect(noslash.languageVersion, null); + expect(noslash.relativeRoot, true); expect(config.extraData, { "generator": "pub", From 9bf6b87cb42b2817d0c0d8cb874268ee6d6c07f3 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Thu, 28 Jan 2021 16:24:37 +0100 Subject: [PATCH 168/281] Migrate to GitHub Actions (dart-lang/package_config#103) --- .../.github/workflows/test-package.yml | 61 +++++++++++++++++++ pkgs/package_config/.travis.yml | 21 ------- pkgs/package_config/README.md | 2 +- 3 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 pkgs/package_config/.github/workflows/test-package.yml delete mode 100644 pkgs/package_config/.travis.yml diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml new file mode 100644 index 000000000..20220ab61 --- /dev/null +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -0,0 +1,61 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run tests + run: dart run build_runner test -- -p chrome,vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/package_config/.travis.yml b/pkgs/package_config/.travis.yml deleted file mode 100644 index c4e5bdb8f..000000000 --- a/pkgs/package_config/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: dart -sudo: false -dart: - - dev -dart_task: - - test - - dartfmt - - dart analyze --fatal-infos . - -matrix: - include: - - dart: dev - script: pub run build_runner test -- -p chrome - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 1ad4b41c1..ada1bd0ec 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/dart-lang/package_config.svg?branch=master)](https://travis-ci.org/dart-lang/package_config) +[![Build Status](https://github.com/dart-lang/package_config/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/package_config/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) Support for working with **Package Configuration** files as described From 2d1b038528c3c1053f46ce72d8c581e19ca986f4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 17:22:57 -0800 Subject: [PATCH 169/281] Prepare to publish for stable null safety (dart-lang/pool#52) --- pkgs/pool/CHANGELOG.md | 6 +++++- pkgs/pool/pubspec.yaml | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 6fd755bbb..9e0a5a519 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.0 + +* Stable release for null safety. + ## 1.5.0-nullsafety.3 * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release @@ -15,7 +19,7 @@ * Migrate to null safety. * `forEach`: Avoid `await null` if the `Stream` is not paused. - Improves trivial benchmark by 40%. + Improves trivial benchmark by 40%. ## 1.4.0 diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 67d8b6c7a..421baf5f2 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.0-nullsafety.3 +version: 1.5.0 description: >- Manage a finite pool of resources. @@ -10,8 +10,8 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - async: '>=2.5.0-nullsafety <2.5.0' - stack_trace: '>=1.10.0-nullsafety <1.10.0' + async: ^2.5.0 + stack_trace: ^1.10.0 dev_dependencies: fake_async: ^1.2.0-nullsafety From e96a1b0651fdd5ea397c51baf123ec0e068eedcd Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 5 Feb 2021 09:39:15 -0800 Subject: [PATCH 170/281] stable null safety release, clean up deps (dart-lang/package_config#105) --- pkgs/package_config/pubspec.yaml | 54 ++++++-------------------------- 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5903bc8ac..4f74712d6 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.0-nullsafety.1 +version: 2.0.0 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config @@ -7,53 +7,17 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - path: ^1.8.0-nullsafety.3 + path: ^1.8.0 dev_dependencies: - build_resolvers: ^1.10.0 build_runner: ^1.10.0 - build_runner_core: ^1.10.0 build_test: ^1.3.0 - build_web_compilers: ^2.15.0 - pedantic: ^1.10.0-nullsafety.3 - test: ^1.16.0-nullsafety.4 + build_web_compilers: ^2.12.2 + pedantic: ^1.10.0-nullsafety.0 + test: ^1.16.0-nullsafety.19 +# Required due to dependency cycles dependency_overrides: - _fe_analyzer_shared: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/_fe_analyzer_shared - analyzer: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/analyzer - build_resolvers: - git: - url: git://github.com/dart-lang/build.git - path: build_resolvers - build_runner: - git: - url: git://github.com/dart-lang/build.git - path: build_runner - build_runner_core: - git: - url: git://github.com/dart-lang/build.git - path: build_runner_core - build_test: - git: - url: git://github.com/dart-lang/build.git - path: build_test - coverage: - git: git://github.com/dart-lang/coverage.git - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core + test: ^1.16.0-nullsafety.19 + coverage: ^0.15.1 + analyzer: ^0.41.0 From ec2b4685ecbb4ed93b1e7e8ed8e8519df810d98d Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Tue, 9 Feb 2021 11:53:19 +0100 Subject: [PATCH 171/281] Include duplicate package name in error message (dart-lang/package_config#104) --- pkgs/package_config/lib/src/package_config_impl.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index c75111580..122999106 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -77,7 +77,7 @@ class SimplePackageConfig implements PackageConfig { var name = package.name; if (packageNames.contains(name)) { onError(PackageConfigArgumentError( - name, "packages", "Duplicate package name")); + name, "packages", "Duplicate package name '$name'")); continue; } packageNames.add(name); From 56a74123ffd838842e1bdf6068fa054e975435a2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 19 Mar 2021 13:36:04 -0700 Subject: [PATCH 172/281] Use unique library names (dart-lang/package_config#107) The current dartdocs output does not link correctly because of the conflicting library names. - Use a stable SDK and dependencies. - Test on the oldest supported SDK. - Remove dependency overrides. --- .../.github/workflows/test-package.yml | 2 +- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/lib/package_config_types.dart | 2 +- pkgs/package_config/pubspec.yaml | 14 ++++---------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 20220ab61..d0e1e23e5 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v0.3 diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 4a04782b4..9949b51db 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.1 + +- Use unique library names to correct docs issue. + ## 2.0.0 - Migrate to null safety. diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index f0637b11b..b3fca164c 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -4,7 +4,7 @@ /// A package configuration is a way to assign file paths to package URIs, /// and vice-versa, -library package_config.package_config; +library package_config.package_config_types; export "src/package_config.dart" show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 4f74712d6..1ee725098 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,10 +1,10 @@ name: package_config -version: 2.0.0 +version: 2.0.1 description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: path: ^1.8.0 @@ -13,11 +13,5 @@ dev_dependencies: build_runner: ^1.10.0 build_test: ^1.3.0 build_web_compilers: ^2.12.2 - pedantic: ^1.10.0-nullsafety.0 - test: ^1.16.0-nullsafety.19 - -# Required due to dependency cycles -dependency_overrides: - test: ^1.16.0-nullsafety.19 - coverage: ^0.15.1 - analyzer: ^0.41.0 + pedantic: ^1.10.0 + test: ^1.16.0 From acac15a194ed1dc2daba3524bfabc1a334ca267a Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Thu, 1 Apr 2021 12:47:12 -0700 Subject: [PATCH 173/281] Update LICENSE Changes to comply with internal review --- pkgs/pool/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/LICENSE b/pkgs/pool/LICENSE index 5c60afea3..000cd7bec 100644 --- a/pkgs/pool/LICENSE +++ b/pkgs/pool/LICENSE @@ -1,4 +1,5 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2014, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From f72b4a0098553482101113d83296e078022a2287 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Fri, 2 Apr 2021 16:07:34 -0700 Subject: [PATCH 174/281] Update LICENSE Changes to comply with internal review --- pkgs/package_config/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/LICENSE b/pkgs/package_config/LICENSE index f75d7c237..767000764 100644 --- a/pkgs/package_config/LICENSE +++ b/pkgs/package_config/LICENSE @@ -1,4 +1,5 @@ -Copyright 2019, the Dart project authors. All rights reserved. +Copyright 2019, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 1230976b0a3526edfad0f4b2d69b961ad8e3d26f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 May 2021 12:46:33 -0700 Subject: [PATCH 175/281] Use latest CI setup, test on oldest supported SDK (dart-lang/pool#55) --- pkgs/pool/.github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index f55a818da..9a455e756 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install From c7adc8b35de00acd672991f76dee61d41f75e5c8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 5 Jun 2021 13:28:33 -0700 Subject: [PATCH 176/281] Add dependabot --- pkgs/package_config/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/package_config/.github/dependabot.yml diff --git a/pkgs/package_config/.github/dependabot.yml b/pkgs/package_config/.github/dependabot.yml new file mode 100644 index 000000000..430a85e7d --- /dev/null +++ b/pkgs/package_config/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 273066187fb72762eab1fdc2fbe041bd39086564 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:36:53 -0700 Subject: [PATCH 177/281] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/package_config#110) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index d0e1e23e5..33bf62bd9 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From 8049cb6e3338ffcc00e7c5baaf43af20955a3ef3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 10 Jul 2021 20:59:52 -0700 Subject: [PATCH 178/281] Dart format with latest SDK (dart-lang/package_config#111) --- pkgs/package_config/lib/src/util_io.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart index 8e5f0b88e..9c48f049e 100644 --- a/pkgs/package_config/lib/src/util_io.dart +++ b/pkgs/package_config/lib/src/util_io.dart @@ -98,7 +98,9 @@ String pathJoinAll(Iterable parts) { var buffer = StringBuffer(); var separator = ""; for (var part in parts) { - buffer..write(separator)..write(part); + buffer + ..write(separator) + ..write(part); separator = part.endsWith(Platform.pathSeparator) ? "" : Platform.pathSeparator; } From df19c5c971463a5a744fae21e20de5c7ac8cd8a9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 15 Jul 2021 10:35:22 -0700 Subject: [PATCH 179/281] Update to latest deps, fix remaining lints (dart-lang/package_config#112) --- pkgs/package_config/analysis_options.yaml | 5 - pkgs/package_config/lib/package_config.dart | 26 +- .../lib/package_config_types.dart | 4 +- pkgs/package_config/lib/src/discovery.dart | 42 +- .../lib/src/package_config.dart | 24 +- .../lib/src/package_config_impl.dart | 126 +++--- .../lib/src/package_config_io.dart | 46 +-- .../lib/src/package_config_json.dart | 82 ++-- .../package_config/lib/src/packages_file.dart | 40 +- pkgs/package_config/lib/src/util.dart | 32 +- pkgs/package_config/lib/src/util_io.dart | 22 +- pkgs/package_config/pubspec.yaml | 6 +- pkgs/package_config/test/discovery_test.dart | 208 +++++----- .../test/discovery_uri_test.dart | 182 ++++----- .../test/package_config_impl_test.dart | 144 +++---- pkgs/package_config/test/parse_test.dart | 378 +++++++++--------- pkgs/package_config/test/src/util.dart | 17 +- pkgs/package_config/test/src/util_io.dart | 16 +- 18 files changed, 718 insertions(+), 682 deletions(-) diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml index a7854087c..a0ba68de2 100644 --- a/pkgs/package_config/analysis_options.yaml +++ b/pkgs/package_config/analysis_options.yaml @@ -3,8 +3,3 @@ # BSD-style license that can be found in the LICENSE file. include: package:pedantic/analysis_options.1.9.0.yaml -analyzer: - errors: - annotate_overrides: ignore - prefer_single_quotes: ignore - use_function_type_syntax_for_parameters: ignore diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 3dfd8ef29..bd227e4e5 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -9,15 +9,15 @@ /// configurations in the [specified format](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). library package_config.package_config; -import "dart:io" show File, Directory; -import "dart:typed_data" show Uint8List; +import 'dart:io' show File, Directory; +import 'dart:typed_data' show Uint8List; -import "src/discovery.dart" as discover; -import "src/errors.dart" show throwError; -import "src/package_config.dart"; -import "src/package_config_io.dart"; +import 'src/discovery.dart' as discover; +import 'src/errors.dart' show throwError; +import 'src/package_config.dart'; +import 'src/package_config_io.dart'; -export "package_config_types.dart"; +export 'package_config_types.dart'; /// Reads a specific package configuration file. /// @@ -42,7 +42,7 @@ export "package_config_types.dart"; /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfig(File file, - {bool preferNewest = true, void onError(Object error)?}) => + {bool preferNewest = true, void Function(Object error)? onError}) => readAnyConfigFile(file, preferNewest, onError ?? throwError); /// Reads a specific package configuration URI. @@ -87,9 +87,9 @@ Future loadPackageConfig(File file, /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. Future loadPackageConfigUri(Uri file, - {Future loader(Uri uri)?, + {Future Function(Uri uri)? loader, bool preferNewest = true, - void onError(Object error)?}) => + void Function(Object error)? onError}) => readAnyConfigFileUri(file, loader, onError ?? throwError, preferNewest); /// Finds a package configuration relative to [directory]. @@ -113,7 +113,7 @@ Future loadPackageConfigUri(Uri file, /// /// Returns `null` if no configuration file is found. Future findPackageConfig(Directory directory, - {bool recurse = true, void onError(Object error)?}) => + {bool recurse = true, void Function(Object error)? onError}) => discover.findPackageConfig(directory, recurse, onError ?? throwError); /// Finds a package configuration relative to [location]. @@ -158,8 +158,8 @@ Future findPackageConfig(Directory directory, /// Returns `null` if no configuration file is found. Future findPackageConfigUri(Uri location, {bool recurse = true, - Future loader(Uri uri)?, - void onError(Object error)?}) => + Future Function(Uri uri)? loader, + void Function(Object error)? onError}) => discover.findPackageConfigUri( location, loader, onError ?? throwError, recurse); diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index b3fca164c..482f82ac2 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -6,6 +6,6 @@ /// and vice-versa, library package_config.package_config_types; -export "src/package_config.dart" +export 'src/package_config.dart' show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; -export "src/errors.dart" show PackageConfigError; +export 'src/errors.dart' show PackageConfigError; diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index a3e01d710..a6cc451f2 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -2,21 +2,21 @@ // 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. -import "dart:io"; +import 'dart:io'; import 'dart:typed_data'; import 'package_config_io.dart'; -import "errors.dart"; -import "package_config_impl.dart"; -import "package_config_json.dart"; -import "packages_file.dart" as packages_file; -import "util_io.dart" show defaultLoader, pathJoin; +import 'errors.dart'; +import 'package_config_impl.dart'; +import 'package_config_json.dart'; +import 'packages_file.dart' as packages_file; +import 'util_io.dart' show defaultLoader, pathJoin; -final Uri packageConfigJsonPath = Uri(path: ".dart_tool/package_config.json"); -final Uri dotPackagesPath = Uri(path: ".packages"); -final Uri currentPath = Uri(path: "."); -final Uri parentPath = Uri(path: ".."); +final Uri packageConfigJsonPath = Uri(path: '.dart_tool/package_config.json'); +final Uri dotPackagesPath = Uri(path: '.packages'); +final Uri currentPath = Uri(path: '.'); +final Uri parentPath = Uri(path: '..'); /// Discover the package configuration for a Dart script. /// @@ -32,8 +32,8 @@ final Uri parentPath = Uri(path: ".."); /// If any of these tests succeed, a `PackageConfig` class is returned. /// Returns `null` if no configuration was found. If a configuration /// is needed, then the caller can supply [PackageConfig.empty]. -Future findPackageConfig( - Directory baseDirectory, bool recursive, void onError(Object error)) async { +Future findPackageConfig(Directory baseDirectory, + bool recursive, void Function(Object error) onError) async { var directory = baseDirectory; if (!directory.isAbsolute) directory = directory.absolute; if (!await directory.exists()) { @@ -55,16 +55,16 @@ Future findPackageConfig( /// Similar to [findPackageConfig] but based on a URI. Future findPackageConfigUri( Uri location, - Future loader(Uri uri)?, - void onError(Object error), + Future Function(Uri uri)? loader, + void Function(Object error) onError, bool recursive) async { - if (location.isScheme("package")) { + if (location.isScheme('package')) { onError(PackageConfigArgumentError( - location, "location", "Must not be a package: URI")); + location, 'location', 'Must not be a package: URI')); return null; } if (loader == null) { - if (location.isScheme("file")) { + if (location.isScheme('file')) { return findPackageConfig( Directory.fromUri(location.resolveUri(currentPath)), recursive, @@ -72,7 +72,7 @@ Future findPackageConfigUri( } loader = defaultLoader; } - if (!location.path.endsWith("/")) location = location.resolveUri(currentPath); + if (!location.path.endsWith('/')) location = location.resolveUri(currentPath); while (true) { var file = location.resolveUri(packageConfigJsonPath); var bytes = await loader(file); @@ -103,7 +103,7 @@ Future findPackageConfigUri( /// a best-effort attempt is made to return a package configuration. /// This may be the empty package configuration. Future findPackagConfigInDirectory( - Directory directory, void onError(Object error)) async { + Directory directory, void Function(Object error) onError) async { var packageConfigFile = await checkForPackageConfigJsonFile(directory); if (packageConfigFile != null) { return await readPackageConfigJsonFile(packageConfigFile, onError); @@ -118,13 +118,13 @@ Future findPackagConfigInDirectory( Future checkForPackageConfigJsonFile(Directory directory) async { assert(directory.isAbsolute); var file = - File(pathJoin(directory.path, ".dart_tool", "package_config.json")); + File(pathJoin(directory.path, '.dart_tool', 'package_config.json')); if (await file.exists()) return file; return null; } Future checkForDotPackagesFile(Directory directory) async { - var file = File(pathJoin(directory.path, ".packages")); + var file = File(pathJoin(directory.path, '.packages')); if (await file.exists()) return file; return null; } diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 26aa39622..8210132a1 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -5,7 +5,7 @@ import 'dart:typed_data'; import 'errors.dart'; -import "package_config_impl.dart"; +import 'package_config_impl.dart'; import 'package_config_json.dart'; /// A package configuration. @@ -70,7 +70,7 @@ abstract class PackageConfig { /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. static PackageConfig parseBytes(Uint8List bytes, Uri baseUri, - {void onError(Object error)?}) => + {void Function(Object error)? onError}) => parsePackageConfigBytes(bytes, baseUri, onError ?? throwError); /// Parses a package configuration file. @@ -90,7 +90,7 @@ abstract class PackageConfig { /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. static PackageConfig parseString(String configuration, Uri baseUri, - {void onError(Object error)?}) => + {void Function(Object error)? onError}) => parsePackageConfigString(configuration, baseUri, onError ?? throwError); /// Parses the JSON data of a package configuration file. @@ -111,7 +111,7 @@ abstract class PackageConfig { /// The result may be [PackageConfig.empty] if there is no way to /// extract useful information from the bytes. static PackageConfig parseJson(Object? jsonData, Uri baseUri, - {void onError(Object error)?}) => + {void Function(Object error)? onError}) => parsePackageConfigJson(jsonData, baseUri, onError ?? throwError); /// Writes a configuration file for this configuration on [output]. @@ -302,8 +302,8 @@ abstract class LanguageVersion implements Comparable { /// The maximal value allowed by [major] and [minor] values; static const int maxValue = 0x7FFFFFFF; factory LanguageVersion(int major, int minor) { - RangeError.checkValueInInterval(major, 0, maxValue, "major"); - RangeError.checkValueInInterval(minor, 0, maxValue, "major"); + RangeError.checkValueInInterval(major, 0, maxValue, 'major'); + RangeError.checkValueInInterval(minor, 0, maxValue, 'major'); return SimpleLanguageVersion(major, minor, null); } @@ -324,7 +324,8 @@ abstract class LanguageVersion implements Comparable { /// If [onError] is not supplied, it defaults to throwing the exception. /// If the call does not throw, then an [InvalidLanguageVersion] is returned /// containing the original [source]. - static LanguageVersion parse(String source, {void onError(Object error)?}) => + static LanguageVersion parse(String source, + {void Function(Object error)? onError}) => parseLanguageVersion(source, onError ?? throwError); /// The major language version. @@ -352,6 +353,7 @@ abstract class LanguageVersion implements Comparable { /// is greater than the latter's major version, or if they have /// the same major version and the former's minor version is greater than /// the latter's. + @override int compareTo(LanguageVersion other); /// Valid language versions with the same [major] and [minor] values are @@ -359,14 +361,17 @@ abstract class LanguageVersion implements Comparable { /// /// Invalid language versions ([InvalidLanguageVersion]) are not equal to /// any other object. + @override bool operator ==(Object other); + @override int get hashCode; /// A string representation of the language version. /// /// A valid language version is represented as /// `"${version.major}.${version.minor}"`. + @override String toString(); } @@ -377,16 +382,21 @@ abstract class LanguageVersion implements Comparable { /// which did not throw on an error. abstract class InvalidLanguageVersion implements LanguageVersion { /// The value -1 for an invalid language version. + @override int get major; /// The value -1 for an invalid language version. + @override int get minor; /// An invalid language version is only equal to itself. + @override bool operator ==(Object other); + @override int get hashCode; /// The original invalid version string. + @override String toString(); } diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 122999106..4167d35f8 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -3,21 +3,23 @@ // BSD-style license that can be found in the LICENSE file. import 'errors.dart'; -import "package_config.dart"; -import "util.dart"; +import 'package_config.dart'; +import 'util.dart'; -export "package_config.dart"; +export 'package_config.dart'; // Implementations of the main data types exposed by the API of this package. class SimplePackageConfig implements PackageConfig { + @override final int version; final Map _packages; final PackageTree _packageTree; + @override final Object? extraData; factory SimplePackageConfig(int version, Iterable packages, - [Object? extraData, void onError(Object error)?]) { + [Object? extraData, void Function(Object error)? onError]) { onError ??= throwError; var validVersion = _validateVersion(version, onError); var sortedPackages = [...packages]..sort(_compareRoot); @@ -39,17 +41,18 @@ class SimplePackageConfig implements PackageConfig { _packages = const {}, extraData = null; - static int _validateVersion(int version, void onError(Object error)) { + static int _validateVersion( + int version, void Function(Object error) onError) { if (version < 0 || version > PackageConfig.maxVersion) { - onError(PackageConfigArgumentError(version, "version", - "Must be in the range 1 to ${PackageConfig.maxVersion}")); + onError(PackageConfigArgumentError(version, 'version', + 'Must be in the range 1 to ${PackageConfig.maxVersion}')); return 2; // The minimal version supporting a SimplePackageConfig. } return version; } static PackageTree _validatePackages(Iterable originalPackages, - List packages, void onError(Object error)) { + List packages, void Function(Object error) onError) { var packageNames = {}; var tree = MutablePackageTree(); for (var originalPackage in packages) { @@ -64,8 +67,8 @@ class SimplePackageConfig implements PackageConfig { originalPackage.extraData, originalPackage.relativeRoot, (error) { if (error is PackageConfigArgumentError) { - onError(PackageConfigArgumentError(packages, "packages", - "Package ${package!.name}: ${error.message}")); + onError(PackageConfigArgumentError(packages, 'packages', + 'Package ${package!.name}: ${error.message}')); } else { onError(error); } @@ -77,7 +80,7 @@ class SimplePackageConfig implements PackageConfig { var name = package.name; if (packageNames.contains(name)) { onError(PackageConfigArgumentError( - name, "packages", "Duplicate package name '$name'")); + name, 'packages', "Duplicate package name '$name'")); continue; } packageNames.add(name); @@ -88,20 +91,20 @@ class SimplePackageConfig implements PackageConfig { if (error.isRootConflict) { onError(PackageConfigArgumentError( originalPackages, - "packages", - "Packages ${package!.name} and ${existingPackage.name} " - "have the same root directory: ${package.root}.\n")); + 'packages', + 'Packages ${package!.name} and ${existingPackage.name} ' + 'have the same root directory: ${package.root}.\n')); } else { assert(error.isPackageRootConflict); // Package is inside the package URI root of the existing package. onError(PackageConfigArgumentError( originalPackages, - "packages", - "Package ${package!.name} is inside the package URI root of " - "package ${existingPackage.name}.\n" - "${existingPackage.name} URI root: " - "${existingPackage.packageUriRoot}\n" - "${package.name} root: ${package.root}\n")); + 'packages', + 'Package ${package!.name} is inside the package URI root of ' + 'package ${existingPackage.name}.\n' + '${existingPackage.name} URI root: ' + '${existingPackage.packageUriRoot}\n' + '${package.name} root: ${package.root}\n')); } } else { // Any other error. @@ -112,8 +115,10 @@ class SimplePackageConfig implements PackageConfig { return tree; } + @override Iterable get packages => _packages.values; + @override Package? operator [](String packageName) => _packages[packageName]; /// Provides the associated package for a specific [file] (or directory). @@ -122,22 +127,25 @@ class SimplePackageConfig implements PackageConfig { /// That is, the [Package.rootUri] directory is a parent directory /// of the [file]'s location. /// Returns `null` if the file does not belong to any package. + @override Package? packageOf(Uri file) => _packageTree.packageOf(file); + @override Uri? resolve(Uri packageUri) { - var packageName = checkValidPackageUri(packageUri, "packageUri"); + var packageName = checkValidPackageUri(packageUri, 'packageUri'); return _packages[packageName]?.packageUriRoot.resolveUri( Uri(path: packageUri.path.substring(packageName.length + 1))); } + @override Uri? toPackageUri(Uri nonPackageUri) { - if (nonPackageUri.isScheme("package")) { + if (nonPackageUri.isScheme('package')) { throw PackageConfigArgumentError( - nonPackageUri, "nonPackageUri", "Must not be a package URI"); + nonPackageUri, 'nonPackageUri', 'Must not be a package URI'); } if (nonPackageUri.hasQuery || nonPackageUri.hasFragment) { - throw PackageConfigArgumentError(nonPackageUri, "nonPackageUri", - "Must not have query or fragment part"); + throw PackageConfigArgumentError(nonPackageUri, 'nonPackageUri', + 'Must not have query or fragment part'); } // Find package that file belongs to. var package = _packageTree.packageOf(nonPackageUri); @@ -147,7 +155,7 @@ class SimplePackageConfig implements PackageConfig { var root = package.packageUriRoot.toString(); if (_beginsWith(package.root.toString().length, root, path)) { var rest = path.substring(root.length); - return Uri(scheme: "package", path: "${package.name}/$rest"); + return Uri(scheme: 'package', path: '${package.name}/$rest'); } return null; } @@ -155,11 +163,17 @@ class SimplePackageConfig implements PackageConfig { /// Configuration data for a single package. class SimplePackage implements Package { + @override final String name; + @override final Uri root; + @override final Uri packageUriRoot; + @override final LanguageVersion? languageVersion; + @override final Object? extraData; + @override final bool relativeRoot; SimplePackage._(this.name, this.root, this.packageUriRoot, @@ -187,30 +201,30 @@ class SimplePackage implements Package { LanguageVersion? languageVersion, Object? extraData, bool relativeRoot, - void onError(Object error)) { + void Function(Object error) onError) { var fatalError = false; var invalidIndex = checkPackageName(name); if (invalidIndex >= 0) { onError(PackageConfigFormatException( - "Not a valid package name", name, invalidIndex)); + 'Not a valid package name', name, invalidIndex)); fatalError = true; } - if (root.isScheme("package")) { + if (root.isScheme('package')) { onError(PackageConfigArgumentError( - "$root", "root", "Must not be a package URI")); + '$root', 'root', 'Must not be a package URI')); fatalError = true; } else if (!isAbsoluteDirectoryUri(root)) { onError(PackageConfigArgumentError( - "$root", - "root", - "In package $name: Not an absolute URI with no query or fragment " - "with a path ending in /")); + '$root', + 'root', + 'In package $name: Not an absolute URI with no query or fragment ' + 'with a path ending in /')); // Try to recover. If the URI has a scheme, // then ensure that the path ends with `/`. if (!root.hasScheme) { fatalError = true; - } else if (!root.path.endsWith("/")) { - root = root.replace(path: root.path + "/"); + } else if (!root.path.endsWith('/')) { + root = root.replace(path: root.path + '/'); } } if (packageUriRoot == null) { @@ -220,13 +234,13 @@ class SimplePackage implements Package { if (!isAbsoluteDirectoryUri(packageUriRoot)) { onError(PackageConfigArgumentError( packageUriRoot, - "packageUriRoot", - "In package $name: Not an absolute URI with no query or fragment " - "with a path ending in /")); + 'packageUriRoot', + 'In package $name: Not an absolute URI with no query or fragment ' + 'with a path ending in /')); packageUriRoot = root; } else if (!isUriPrefix(root, packageUriRoot)) { - onError(PackageConfigArgumentError(packageUriRoot, "packageUriRoot", - "The package URI root is not below the package root")); + onError(PackageConfigArgumentError(packageUriRoot, 'packageUriRoot', + 'The package URI root is not below the package root')); packageUriRoot = root; } } @@ -243,7 +257,7 @@ class SimplePackage implements Package { /// Reports a format exception on [onError] if not, or if the numbers /// are too large (at most 32-bit signed integers). LanguageVersion parseLanguageVersion( - String? source, void onError(Object error)) { + String? source, void Function(Object error) onError) { var index = 0; // Reads a positive decimal numeral. Returns the value of the numeral, // or a negative number in case of an error. @@ -254,7 +268,7 @@ LanguageVersion parseLanguageVersion( int readNumeral() { const maxValue = 0x7FFFFFFF; if (index == source!.length) { - onError(PackageConfigFormatException("Missing number", source, index)); + onError(PackageConfigFormatException('Missing number', source, index)); return -1; } var start = index; @@ -262,7 +276,7 @@ LanguageVersion parseLanguageVersion( var char = source.codeUnitAt(index); var digit = char ^ 0x30; if (digit > 9) { - onError(PackageConfigFormatException("Missing number", source, index)); + onError(PackageConfigFormatException('Missing number', source, index)); return -1; } var firstDigit = digit; @@ -271,7 +285,7 @@ LanguageVersion parseLanguageVersion( value = value * 10 + digit; if (value > maxValue) { onError( - PackageConfigFormatException("Number too large", source, start)); + PackageConfigFormatException('Number too large', source, start)); return -1; } index++; @@ -281,7 +295,7 @@ LanguageVersion parseLanguageVersion( } while (digit <= 9); if (firstDigit == 0 && index > start + 1) { onError(PackageConfigFormatException( - "Leading zero not allowed", source, start)); + 'Leading zero not allowed', source, start)); } return value; } @@ -301,13 +315,14 @@ LanguageVersion parseLanguageVersion( } if (index != source.length) { onError(PackageConfigFormatException( - "Unexpected trailing character", source, index)); + 'Unexpected trailing character', source, index)); return SimpleInvalidLanguageVersion(source); } return SimpleLanguageVersion(major, minor, source); } abstract class _SimpleLanguageVersionBase implements LanguageVersion { + @override int compareTo(LanguageVersion other) { var result = major.compareTo(other.major); if (result != 0) return result; @@ -316,26 +331,34 @@ abstract class _SimpleLanguageVersionBase implements LanguageVersion { } class SimpleLanguageVersion extends _SimpleLanguageVersionBase { + @override final int major; + @override final int minor; String? _source; SimpleLanguageVersion(this.major, this.minor, this._source); + @override bool operator ==(Object other) => other is LanguageVersion && major == other.major && minor == other.minor; + @override int get hashCode => (major * 17 ^ minor * 37) & 0x3FFFFFFF; - String toString() => _source ??= "$major.$minor"; + @override + String toString() => _source ??= '$major.$minor'; } class SimpleInvalidLanguageVersion extends _SimpleLanguageVersionBase implements InvalidLanguageVersion { final String? _source; SimpleInvalidLanguageVersion(this._source); + @override int get major => -1; + @override int get minor => -1; + @override String toString() => _source!; } @@ -374,6 +397,7 @@ class MutablePackageTree implements PackageTree { /// there is no tree object associated with it. Map? _packageChildren; + @override Iterable get allPackages sync* { for (var package in packages) { yield package; @@ -399,7 +423,8 @@ class MutablePackageTree implements PackageTree { /// /// The packages are added in order of their root path. /// It is never necessary to insert a node between two existing levels. - void add(int start, SimplePackage package, void onError(Object error)) { + void add( + int start, SimplePackage package, void Function(Object error) onError) { var path = package.root.toString(); for (var treePackage in packages) { // Check is package is inside treePackage. @@ -428,6 +453,7 @@ class MutablePackageTree implements PackageTree { packages.add(package); } + @override SimplePackage? packageOf(Uri file) { return findPackageOf(0, file.toString()); } @@ -471,8 +497,10 @@ class MutablePackageTree implements PackageTree { class EmptyPackageTree implements PackageTree { const EmptyPackageTree(); + @override Iterable get allPackages => const Iterable.empty(); + @override SimplePackage? packageOf(Uri file) => null; } diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index d3e59be47..9aed621e0 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -4,31 +4,31 @@ // dart:io dependent functionality for reading and writing configuration files. -import "dart:convert"; -import "dart:io"; -import "dart:typed_data"; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; -import "errors.dart"; -import "package_config_impl.dart"; -import "package_config_json.dart"; -import "packages_file.dart" as packages_file; -import "util.dart"; -import "util_io.dart"; +import 'errors.dart'; +import 'package_config_impl.dart'; +import 'package_config_json.dart'; +import 'packages_file.dart' as packages_file; +import 'util.dart'; +import 'util_io.dart'; /// Name of directory where Dart tools store their configuration. /// /// Directory is created in the package root directory. -const dartToolDirName = ".dart_tool"; +const dartToolDirName = '.dart_tool'; /// Name of file containing new package configuration data. /// /// File is stored in the dart tool directory. -const packageConfigFileName = "package_config.json"; +const packageConfigFileName = 'package_config.json'; /// Name of file containing legacy package configuration data. /// /// File is stored in the package root directory. -const packagesFileName = ".packages"; +const packagesFileName = '.packages'; /// Reads a package configuration file. /// @@ -43,7 +43,7 @@ const packagesFileName = ".packages"; /// /// The file must exist and be a normal file. Future readAnyConfigFile( - File file, bool preferNewest, void onError(Object error)) async { + File file, bool preferNewest, void Function(Object error) onError) async { if (preferNewest && fileName(file.path) == packagesFileName) { var alternateFile = File( pathJoin(dirName(file.path), dartToolDirName, packageConfigFileName)); @@ -64,21 +64,21 @@ Future readAnyConfigFile( /// Like [readAnyConfigFile] but uses a URI and an optional loader. Future readAnyConfigFileUri( Uri file, - Future loader(Uri uri)?, - void onError(Object error), + Future Function(Uri uri)? loader, + void Function(Object error) onError, bool preferNewest) async { - if (file.isScheme("package")) { + if (file.isScheme('package')) { throw PackageConfigArgumentError( - file, "file", "Must not be a package: URI"); + file, 'file', 'Must not be a package: URI'); } if (loader == null) { - if (file.isScheme("file")) { + if (file.isScheme('file')) { return await readAnyConfigFile(File.fromUri(file), preferNewest, onError); } loader = defaultLoader; } if (preferNewest && file.pathSegments.last == packagesFileName) { - var alternateFile = file.resolve("$dartToolDirName/$packageConfigFileName"); + var alternateFile = file.resolve('$dartToolDirName/$packageConfigFileName'); Uint8List? bytes; try { bytes = await loader(alternateFile); @@ -99,7 +99,7 @@ Future readAnyConfigFileUri( } if (bytes == null) { onError(PackageConfigArgumentError( - file.toString(), "file", "File cannot be read")); + file.toString(), 'file', 'File cannot be read')); return const SimplePackageConfig.empty(); } return parseAnyConfigFile(bytes, file, onError); @@ -110,7 +110,7 @@ Future readAnyConfigFileUri( /// Assumes it's a JSON file if the first non-whitespace character /// is `{`, otherwise assumes it's a `.packages` file. PackageConfig parseAnyConfigFile( - Uint8List bytes, Uri file, void onError(Object error)) { + Uint8List bytes, Uri file, void Function(Object error) onError) { var firstChar = firstNonWhitespaceChar(bytes); if (firstChar != $lbrace) { // Definitely not a JSON object, probably a .packages. @@ -120,7 +120,7 @@ PackageConfig parseAnyConfigFile( } Future readPackageConfigJsonFile( - File file, void onError(Object error)) async { + File file, void Function(Object error) onError) async { Uint8List bytes; try { bytes = await file.readAsBytes(); @@ -132,7 +132,7 @@ Future readPackageConfigJsonFile( } Future readDotPackagesFile( - File file, void onError(Object error)) async { + File file, void Function(Object error) onError) async { Uint8List bytes; try { bytes = await file.readAsBytes(); diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 979c35ed4..1998b6606 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -4,21 +4,21 @@ // Parsing and serialization of package configurations. -import "dart:convert"; -import "dart:typed_data"; +import 'dart:convert'; +import 'dart:typed_data'; -import "errors.dart"; -import "package_config_impl.dart"; -import "packages_file.dart" as packages_file; -import "util.dart"; +import 'errors.dart'; +import 'package_config_impl.dart'; +import 'packages_file.dart' as packages_file; +import 'util.dart'; -const String _configVersionKey = "configVersion"; -const String _packagesKey = "packages"; +const String _configVersionKey = 'configVersion'; +const String _packagesKey = 'packages'; const List _topNames = [_configVersionKey, _packagesKey]; -const String _nameKey = "name"; -const String _rootUriKey = "rootUri"; -const String _packageUriKey = "packageUri"; -const String _languageVersionKey = "languageVersion"; +const String _nameKey = 'name'; +const String _rootUriKey = 'rootUri'; +const String _packageUriKey = 'packageUri'; +const String _languageVersionKey = 'languageVersion'; const List _packageNames = [ _nameKey, _rootUriKey, @@ -26,14 +26,14 @@ const List _packageNames = [ _languageVersionKey ]; -const String _generatedKey = "generated"; -const String _generatorKey = "generator"; -const String _generatorVersionKey = "generatorVersion"; +const String _generatedKey = 'generated'; +const String _generatorKey = 'generator'; +const String _generatorVersionKey = 'generatorVersion'; final _jsonUtf8Decoder = json.fuse(utf8).decoder; PackageConfig parsePackageConfigBytes( - Uint8List bytes, Uri file, void onError(Object error)) { + Uint8List bytes, Uri file, void Function(Object error) onError) { // TODO(lrn): Make this simpler. Maybe parse directly from bytes. var jsonObject; try { @@ -46,7 +46,7 @@ PackageConfig parsePackageConfigBytes( } PackageConfig parsePackageConfigString( - String source, Uri file, void onError(Object error)) { + String source, Uri file, void Function(Object error) onError) { var jsonObject; try { jsonObject = jsonDecode(source); @@ -80,21 +80,21 @@ PackageConfig parsePackageConfigString( /// The [baseLocation] is used as base URI to resolve the "rootUri" /// URI referencestring. PackageConfig parsePackageConfigJson( - Object? json, Uri baseLocation, void onError(Object error)) { - if (!baseLocation.hasScheme || baseLocation.isScheme("package")) { - throw PackageConfigArgumentError(baseLocation.toString(), "baseLocation", - "Must be an absolute non-package: URI"); + Object? json, Uri baseLocation, void Function(Object error) onError) { + if (!baseLocation.hasScheme || baseLocation.isScheme('package')) { + throw PackageConfigArgumentError(baseLocation.toString(), 'baseLocation', + 'Must be an absolute non-package: URI'); } - if (!baseLocation.path.endsWith("/")) { - baseLocation = baseLocation.resolveUri(Uri(path: ".")); + if (!baseLocation.path.endsWith('/')) { + baseLocation = baseLocation.resolveUri(Uri(path: '.')); } String typeName() { - if (0 is T) return "int"; - if ("" is T) return "string"; - if (const [] is T) return "array"; - return "object"; + if (0 is T) return 'int'; + if ('' is T) return 'string'; + if (const [] is T) return 'array'; + return 'object'; } T? checkType(Object? value, String name, [String? packageName]) { @@ -103,7 +103,7 @@ PackageConfig parsePackageConfigJson( // and Map. Recognize which to give a better error message. var message = "$name${packageName != null ? " of package $packageName" : ""}" - " is not a JSON ${typeName()}"; + ' is not a JSON ${typeName()}'; onError(PackageConfigFormatException(message, value)); return null; } @@ -140,27 +140,27 @@ PackageConfig parsePackageConfigJson( } }); if (!hasName) { - onError(PackageConfigFormatException("Missing name entry", entry)); + onError(PackageConfigFormatException('Missing name entry', entry)); } if (!hasRoot) { - onError(PackageConfigFormatException("Missing rootUri entry", entry)); + onError(PackageConfigFormatException('Missing rootUri entry', entry)); } if (name == null || rootUri == null) return null; var parsedRootUri = Uri.parse(rootUri!); var relativeRoot = !hasAbsolutePath(parsedRootUri); var root = baseLocation.resolveUri(parsedRootUri); - if (!root.path.endsWith("/")) root = root.replace(path: root.path + "/"); + if (!root.path.endsWith('/')) root = root.replace(path: root.path + '/'); var packageRoot = root; if (packageUri != null) packageRoot = root.resolve(packageUri!); - if (!packageRoot.path.endsWith("/")) { - packageRoot = packageRoot.replace(path: packageRoot.path + "/"); + if (!packageRoot.path.endsWith('/')) { + packageRoot = packageRoot.replace(path: packageRoot.path + '/'); } LanguageVersion? version; if (languageVersion != null) { version = parseLanguageVersion(languageVersion, onError); } else if (hasVersion) { - version = SimpleInvalidLanguageVersion("invalid"); + version = SimpleInvalidLanguageVersion('invalid'); } return SimplePackage.validate( @@ -174,7 +174,7 @@ PackageConfig parsePackageConfigJson( }); } - var map = checkType>(json, "value"); + var map = checkType>(json, 'value'); if (map == null) return const SimplePackageConfig.empty(); Map? extraData; List? packageList; @@ -189,7 +189,7 @@ PackageConfig parsePackageConfigJson( var packages = []; for (var package in packageArray) { var packageMap = - checkType>(package, "package entry"); + checkType>(package, 'package entry'); if (packageMap != null) { var entry = parsePackage(packageMap); if (entry != null) { @@ -205,11 +205,11 @@ PackageConfig parsePackageConfigJson( } }); if (configVersion == null) { - onError(PackageConfigFormatException("Missing configVersion entry", json)); + onError(PackageConfigFormatException('Missing configVersion entry', json)); configVersion = 2; } if (packageList == null) { - onError(PackageConfigFormatException("Missing packages list", json)); + onError(PackageConfigFormatException('Missing packages list', json)); packageList = []; } return SimplePackageConfig(configVersion!, packageList!, extraData, (error) { @@ -221,7 +221,7 @@ PackageConfig parsePackageConfigJson( }); } -final _jsonUtf8Encoder = JsonUtf8Encoder(" "); +final _jsonUtf8Encoder = JsonUtf8Encoder(' '); void writePackageConfigJsonUtf8( PackageConfig config, Uri? baseUri, Sink> output) { @@ -234,7 +234,7 @@ void writePackageConfigJsonString( PackageConfig config, Uri? baseUri, StringSink output) { // Can be optimized. var data = packageConfigToJson(config, baseUri); - output.write(JsonEncoder.withIndent(" ").convert(data)); + output.write(JsonEncoder.withIndent(' ').convert(data)); } Map packageConfigToJson(PackageConfig config, Uri? baseUri) => @@ -270,7 +270,7 @@ void writeDotPackages(PackageConfig config, Uri baseUri, StringSink output) { if (generator is String) { var generated = extraData[_generatedKey]; var generatorVersion = extraData[_generatorVersionKey]; - comment = "Generated by $generator" + comment = 'Generated by $generator' "${generatorVersion is String ? " $generatorVersion" : ""}" "${generated is String ? " on $generated" : ""}."; } diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index ddcf8563b..244663326 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -2,10 +2,10 @@ // 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. -import "package_config_impl.dart"; +import 'package_config_impl.dart'; -import "util.dart"; -import "errors.dart"; +import 'util.dart'; +import 'errors.dart'; /// The language version prior to the release of language versioning. /// @@ -31,10 +31,10 @@ final LanguageVersion _languageVersion = LanguageVersion(2, 7); /// [Package.packageUriRoot] is the same as its [Package.root] /// and it has no [Package.languageVersion]. PackageConfig parse( - List source, Uri baseLocation, void onError(Object error)) { - if (baseLocation.isScheme("package")) { + List source, Uri baseLocation, void Function(Object error) onError) { + if (baseLocation.isScheme('package')) { onError(PackageConfigArgumentError( - baseLocation, "baseLocation", "Must not be a package: URI")); + baseLocation, 'baseLocation', 'Must not be a package: URI')); return PackageConfig.empty; } var index = 0; @@ -51,7 +51,7 @@ PackageConfig parse( } if (char == $colon) { onError(PackageConfigFormatException( - "Missing package name", source, index - 1)); + 'Missing package name', source, index - 1)); ignoreLine = true; // Ignore if package name is invalid. } else { ignoreLine = char == $hash; // Ignore if comment. @@ -81,16 +81,16 @@ PackageConfig parse( var invalidIndex = checkPackageName(packageName); if (invalidIndex >= 0) { onError(PackageConfigFormatException( - "Not a valid package name", source, start + invalidIndex)); + 'Not a valid package name', source, start + invalidIndex)); continue; } if (queryStart >= 0) { onError(PackageConfigFormatException( - "Location URI must not have query", source, queryStart)); + 'Location URI must not have query', source, queryStart)); end = queryStart; } else if (fragmentStart >= 0) { onError(PackageConfigFormatException( - "Location URI must not have fragment", source, fragmentStart)); + 'Location URI must not have fragment', source, fragmentStart)); end = fragmentStart; } var packageValue = String.fromCharCodes(source, separatorIndex + 1, end); @@ -103,23 +103,23 @@ PackageConfig parse( } var relativeRoot = !hasAbsolutePath(packageLocation); packageLocation = baseLocation.resolveUri(packageLocation); - if (packageLocation.isScheme("package")) { + if (packageLocation.isScheme('package')) { onError(PackageConfigFormatException( - "Package URI as location for package", source, separatorIndex + 1)); + 'Package URI as location for package', source, separatorIndex + 1)); continue; } var path = packageLocation.path; if (!path.endsWith('/')) { - path += "/"; + path += '/'; packageLocation = packageLocation.replace(path: path); } if (packageNames.contains(packageName)) { onError(PackageConfigFormatException( - "Same package name occured more than once", source, start)); + 'Same package name occured more than once', source, start)); continue; } var rootUri = packageLocation; - if (path.endsWith("/lib/")) { + if (path.endsWith('/lib/')) { // Assume default Pub package layout. Include package itself in root. rootUri = packageLocation.replace(path: path.substring(0, path.length - 4)); @@ -158,7 +158,7 @@ PackageConfig parse( void write(StringSink output, PackageConfig config, {Uri? baseUri, String? comment}) { if (baseUri != null && !baseUri.isAbsolute) { - throw PackageConfigArgumentError(baseUri, "baseUri", "Must be absolute"); + throw PackageConfigArgumentError(baseUri, 'baseUri', 'Must be absolute'); } if (comment != null) { @@ -169,7 +169,7 @@ void write(StringSink output, PackageConfig config, output.writeln(commentLine); } } else { - output.write("# generated by package:package_config at "); + output.write('# generated by package:package_config at '); output.write(DateTime.now()); output.writeln(); } @@ -179,11 +179,11 @@ void write(StringSink output, PackageConfig config, // Validate packageName. if (!isValidPackageName(packageName)) { throw PackageConfigArgumentError( - config, "config", '"$packageName" is not a valid package name'); + config, 'config', '"$packageName" is not a valid package name'); } - if (uri.scheme == "package") { + if (uri.scheme == 'package') { throw PackageConfigArgumentError( - config, "config", "Package location must not be a package URI: $uri"); + config, 'config', 'Package location must not be a package URI: $uri'); } output.write(packageName); output.write(':'); diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index f490cdc1c..61488ac41 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -5,13 +5,13 @@ /// Utility methods used by more than one library in the package. library package_config.util; -import "errors.dart"; +import 'errors.dart'; // All ASCII characters that are valid in a package name, with space // for all the invalid ones (including space). const String _validPackageNameCharacters = r" ! $ &'()*+,-. 0123456789 ; = " - r"@ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ~ "; + r'@ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ~ '; /// Tests whether something is a valid Dart package name. bool isValidPackageName(String string) { @@ -47,17 +47,17 @@ int checkPackageName(String string) { /// Returns the package name extracted from the package URI, /// which is the path segment between `package:` and the first `/`. String checkValidPackageUri(Uri packageUri, String name) { - if (packageUri.scheme != "package") { - throw PackageConfigArgumentError(packageUri, name, "Not a package: URI"); + if (packageUri.scheme != 'package') { + throw PackageConfigArgumentError(packageUri, name, 'Not a package: URI'); } if (packageUri.hasAuthority) { throw PackageConfigArgumentError( - packageUri, name, "Package URIs must not have a host part"); + packageUri, name, 'Package URIs must not have a host part'); } if (packageUri.hasQuery) { // A query makes no sense if resolved to a file: URI. throw PackageConfigArgumentError( - packageUri, name, "Package URIs must not have a query part"); + packageUri, name, 'Package URIs must not have a query part'); } if (packageUri.hasFragment) { // We could leave the fragment after the URL when resolving, @@ -65,7 +65,7 @@ String checkValidPackageUri(Uri packageUri, String name) { // "package:foo/foo.dart#2" were considered different libraries. // Keep the syntax open in case we ever get multiple libraries in one file. throw PackageConfigArgumentError( - packageUri, name, "Package URIs must not have a fragment part"); + packageUri, name, 'Package URIs must not have a fragment part'); } if (packageUri.path.startsWith('/')) { throw PackageConfigArgumentError( @@ -81,7 +81,7 @@ String checkValidPackageUri(Uri packageUri, String name) { if (badIndex >= 0) { if (packageName.isEmpty) { throw PackageConfigArgumentError( - packageUri, name, "Package names mus be non-empty"); + packageUri, name, 'Package names mus be non-empty'); } if (badIndex == packageName.length) { throw PackageConfigArgumentError(packageUri, name, @@ -89,13 +89,13 @@ String checkValidPackageUri(Uri packageUri, String name) { } assert(badIndex < packageName.length); var badCharCode = packageName.codeUnitAt(badIndex); - var badChar = "U+" + badCharCode.toRadixString(16).padLeft(4, '0'); + var badChar = 'U+' + badCharCode.toRadixString(16).padLeft(4, '0'); if (badCharCode >= 0x20 && badCharCode <= 0x7e) { // Printable character. badChar = "'${packageName[badIndex]}' ($badChar)"; } throw PackageConfigArgumentError( - packageUri, name, "Package names must not contain $badChar"); + packageUri, name, 'Package names must not contain $badChar'); } return packageName; } @@ -110,7 +110,7 @@ bool isAbsoluteDirectoryUri(Uri uri) { if (uri.hasFragment) return false; if (!uri.hasScheme) return false; var path = uri.path; - if (!path.endsWith("/")) return false; + if (!path.endsWith('/')) return false; return true; } @@ -139,8 +139,8 @@ int firstNonWhitespaceChar(List bytes) { /// Appends a trailing `/` if the path doesn't end with one. String trailingSlash(String path) { - if (path.isEmpty || path.endsWith("/")) return path; - return path + "/"; + if (path.isEmpty || path.endsWith('/')) return path; + return path + '/'; } /// Whether a URI should not be considered relative to the base URI. @@ -212,15 +212,15 @@ Uri? relativizeUri(Uri? uri, Uri? baseUri) { } if (index == base.length) { if (index == target.length) { - return Uri(path: "./"); + return Uri(path: './'); } return Uri(path: target.skip(index).join('/')); } else if (index > 0) { var buffer = StringBuffer(); for (var n = base.length - index; n > 0; --n) { - buffer.write("../"); + buffer.write('../'); } - buffer.writeAll(target.skip(index), "/"); + buffer.writeAll(target.skip(index), '/'); return Uri(path: buffer.toString()); } else { return uri; diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart index 9c48f049e..914ea384e 100644 --- a/pkgs/package_config/lib/src/util_io.dart +++ b/pkgs/package_config/lib/src/util_io.dart @@ -10,7 +10,7 @@ import 'dart:io'; import 'dart:typed_data'; Future defaultLoader(Uri uri) async { - if (uri.isScheme("file")) { + if (uri.isScheme('file')) { var file = File.fromUri(uri); try { return await file.readAsBytes(); @@ -18,14 +18,14 @@ Future defaultLoader(Uri uri) async { return null; } } - if (uri.isScheme("http") || uri.isScheme("https")) { + if (uri.isScheme('http') || uri.isScheme('https')) { return _httpGet(uri); } - throw UnsupportedError("Default URI unsupported scheme: $uri"); + throw UnsupportedError('Default URI unsupported scheme: $uri'); } Future _httpGet(Uri uri) async { - assert(uri.isScheme("http") || uri.isScheme("https")); + assert(uri.isScheme('http') || uri.isScheme('https')); var client = HttpClient(); var request = await client.getUrl(uri); var response = await request.close(); @@ -72,7 +72,7 @@ String fileName(String path) { String dirName(String path) { var separator = Platform.pathSeparator; var lastSeparator = path.lastIndexOf(separator); - if (lastSeparator < 0) return ""; + if (lastSeparator < 0) return ''; return path.substring(0, lastSeparator); } @@ -82,12 +82,12 @@ String dirName(String path) { /// inserted. String pathJoin(String part1, String part2, [String? part3]) { var separator = Platform.pathSeparator; - var separator1 = part1.endsWith(separator) ? "" : separator; + var separator1 = part1.endsWith(separator) ? '' : separator; if (part3 == null) { - return "$part1$separator1$part2"; + return '$part1$separator1$part2'; } - var separator2 = part2.endsWith(separator) ? "" : separator; - return "$part1$separator1$part2$separator2$part3"; + var separator2 = part2.endsWith(separator) ? '' : separator; + return '$part1$separator1$part2$separator2$part3'; } /// Join an unknown number of path parts with [Platform.pathSeparator]. @@ -96,13 +96,13 @@ String pathJoin(String part1, String part2, [String? part3]) { /// inserted. String pathJoinAll(Iterable parts) { var buffer = StringBuffer(); - var separator = ""; + var separator = ''; for (var part in parts) { buffer ..write(separator) ..write(part); separator = - part.endsWith(Platform.pathSeparator) ? "" : Platform.pathSeparator; + part.endsWith(Platform.pathSeparator) ? '' : Platform.pathSeparator; } return buffer.toString(); } diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 1ee725098..687c3d303 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -10,8 +10,8 @@ dependencies: path: ^1.8.0 dev_dependencies: - build_runner: ^1.10.0 - build_test: ^1.3.0 - build_web_compilers: ^2.12.2 + build_runner: ^2.0.0 + build_test: ^2.1.2 + build_web_compilers: ^3.0.0 pedantic: ^1.10.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index df2374d0b..d2c3d8330 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -5,21 +5,21 @@ @TestOn('vm') library package_config.discovery_test; -import "dart:io"; -import "package:test/test.dart"; -import "package:package_config/package_config.dart"; +import 'dart:io'; +import 'package:test/test.dart'; +import 'package:package_config/package_config.dart'; -import "src/util.dart"; -import "src/util_io.dart"; +import 'src/util.dart'; +import 'src/util_io.dart'; -const packagesFile = """ +const packagesFile = ''' # A comment foo:file:///dart/packages/foo/ bar:/dart/packages/bar/ baz:packages/baz/ -"""; +'''; -const packageConfigFile = """ +const packageConfigFile = ''' { "configVersion": 2, "packages": [ @@ -38,29 +38,29 @@ const packageConfigFile = """ ], "extra": [42] } -"""; +'''; void validatePackagesFile(PackageConfig resolver, Directory directory) { expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(Uri.parse("file:///dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(Uri.directory(directory.path).resolve("packages/baz/qux/foo"))); + expect(resolver.resolve(pkg('foo', 'bar/baz')), + equals(Uri.parse('file:///dart/packages/foo/bar/baz'))); + expect(resolver.resolve(pkg('bar', 'baz/qux')), + equals(Uri.parse('file:///dart/packages/bar/baz/qux'))); + expect(resolver.resolve(pkg('baz', 'qux/foo')), + equals(Uri.directory(directory.path).resolve('packages/baz/qux/foo'))); expect([for (var p in resolver.packages) p.name], - unorderedEquals(["foo", "bar", "baz"])); + unorderedEquals(['foo', 'bar', 'baz'])); } void main() { - group("findPackages", () { + group('findPackages', () { // Finds package_config.json if there. - fileTest("package_config.json", { - ".packages": "invalid .packages file", - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}}, - ".dart_tool": { - "package_config.json": packageConfigFile, + fileTest('package_config.json', { + '.packages': 'invalid .packages file', + 'script.dart': 'main(){}', + 'packages': {'shouldNotBeFound': {}}, + '.dart_tool': { + 'package_config.json': packageConfigFile, } }, (Directory directory) async { var config = (await findPackageConfig(directory))!; @@ -69,10 +69,10 @@ void main() { }); // Finds .packages if no package_config.json. - fileTest(".packages", { - ".packages": packagesFile, - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}} + fileTest('.packages', { + '.packages': packagesFile, + 'script.dart': 'main(){}', + 'packages': {'shouldNotBeFound': {}} }, (Directory directory) async { var config = (await findPackageConfig(directory))!; expect(config.version, 1); // Found .packages file. @@ -80,68 +80,68 @@ void main() { }); // Finds package_config.json in super-directory. - fileTest("package_config.json recursive", { - ".packages": packagesFile, - ".dart_tool": { - "package_config.json": packageConfigFile, + fileTest('package_config.json recursive', { + '.packages': packagesFile, + '.dart_tool': { + 'package_config.json': packageConfigFile, }, - "subdir": { - "script.dart": "main(){}", + 'subdir': { + 'script.dart': 'main(){}', } }, (Directory directory) async { - var config = (await findPackageConfig(subdir(directory, "subdir/")))!; + var config = (await findPackageConfig(subdir(directory, 'subdir/')))!; expect(config.version, 2); validatePackagesFile(config, directory); }); // Finds .packages in super-directory. - fileTest(".packages recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} + fileTest('.packages recursive', { + '.packages': packagesFile, + 'subdir': {'script.dart': 'main(){}'} }, (Directory directory) async { var config; - config = await findPackageConfig(subdir(directory, "subdir/")); + config = await findPackageConfig(subdir(directory, 'subdir/')); expect(config.version, 1); validatePackagesFile(config, directory); }); // Does not find a packages/ directory, and returns null if nothing found. - fileTest("package directory packages not supported", { - "packages": { - "foo": {}, + fileTest('package directory packages not supported', { + 'packages': { + 'foo': {}, } }, (Directory directory) async { var config = await findPackageConfig(directory); expect(config, null); }); - group("throws", () { - fileTest("invalid .packages", { - ".packages": "not a .packages file", + group('throws', () { + fileTest('invalid .packages', { + '.packages': 'not a .packages file', }, (Directory directory) { expect(findPackageConfig(directory), throwsA(TypeMatcher())); }); - fileTest("invalid .packages as JSON", { - ".packages": packageConfigFile, + fileTest('invalid .packages as JSON', { + '.packages': packageConfigFile, }, (Directory directory) { expect(findPackageConfig(directory), throwsA(TypeMatcher())); }); - fileTest("invalid .packages", { - ".dart_tool": { - "package_config.json": "not a JSON file", + fileTest('invalid .packages', { + '.dart_tool': { + 'package_config.json': 'not a JSON file', } }, (Directory directory) { expect(findPackageConfig(directory), throwsA(TypeMatcher())); }); - fileTest("invalid .packages as INI", { - ".dart_tool": { - "package_config.json": packagesFile, + fileTest('invalid .packages as INI', { + '.dart_tool': { + 'package_config.json': packagesFile, } }, (Directory directory) { expect(findPackageConfig(directory), @@ -149,9 +149,9 @@ void main() { }); }); - group("handles error", () { - fileTest("invalid .packages", { - ".packages": "not a .packages file", + group('handles error', () { + fileTest('invalid .packages', { + '.packages': 'not a .packages file', }, (Directory directory) async { var hadError = false; await findPackageConfig(directory, @@ -162,8 +162,8 @@ void main() { expect(hadError, true); }); - fileTest("invalid .packages as JSON", { - ".packages": packageConfigFile, + fileTest('invalid .packages as JSON', { + '.packages': packageConfigFile, }, (Directory directory) async { var hadError = false; await findPackageConfig(directory, @@ -174,9 +174,9 @@ void main() { expect(hadError, true); }); - fileTest("invalid package_config not JSON", { - ".dart_tool": { - "package_config.json": "not a JSON file", + fileTest('invalid package_config not JSON', { + '.dart_tool': { + 'package_config.json': 'not a JSON file', } }, (Directory directory) async { var hadError = false; @@ -188,9 +188,9 @@ void main() { expect(hadError, true); }); - fileTest("invalid package config as INI", { - ".dart_tool": { - "package_config.json": packagesFile, + fileTest('invalid package config as INI', { + '.dart_tool': { + 'package_config.json': packagesFile, } }, (Directory directory) async { var hadError = false; @@ -204,86 +204,86 @@ void main() { }); }); - group("loadPackageConfig", () { + group('loadPackageConfig', () { // Load a specific files - group("package_config.json", () { + group('package_config.json', () { var files = { - ".packages": packagesFile, - ".dart_tool": { - "package_config.json": packageConfigFile, + '.packages': packagesFile, + '.dart_tool': { + 'package_config.json': packageConfigFile, }, }; - fileTest("directly", files, (Directory directory) async { + fileTest('directly', files, (Directory directory) async { var file = - dirFile(subdir(directory, ".dart_tool"), "package_config.json"); + dirFile(subdir(directory, '.dart_tool'), 'package_config.json'); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); - fileTest("indirectly through .packages", files, + fileTest('indirectly through .packages', files, (Directory directory) async { - var file = dirFile(directory, ".packages"); + var file = dirFile(directory, '.packages'); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); - fileTest("prefer .packages", files, (Directory directory) async { - var file = dirFile(directory, ".packages"); + fileTest('prefer .packages', files, (Directory directory) async { + var file = dirFile(directory, '.packages'); var config = await loadPackageConfig(file, preferNewest: false); expect(config.version, 1); validatePackagesFile(config, directory); }); }); - fileTest("package_config.json non-default name", { - ".packages": packagesFile, - "subdir": { - "pheldagriff": packageConfigFile, + fileTest('package_config.json non-default name', { + '.packages': packagesFile, + 'subdir': { + 'pheldagriff': packageConfigFile, }, }, (Directory directory) async { - var file = dirFile(directory, "subdir/pheldagriff"); + var file = dirFile(directory, 'subdir/pheldagriff'); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); - fileTest("package_config.json named .packages", { - "subdir": { - ".packages": packageConfigFile, + fileTest('package_config.json named .packages', { + 'subdir': { + '.packages': packageConfigFile, }, }, (Directory directory) async { - var file = dirFile(directory, "subdir/.packages"); + var file = dirFile(directory, 'subdir/.packages'); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); - fileTest(".packages", { - ".packages": packagesFile, + fileTest('.packages', { + '.packages': packagesFile, }, (Directory directory) async { - var file = dirFile(directory, ".packages"); + var file = dirFile(directory, '.packages'); var config = await loadPackageConfig(file); expect(config.version, 1); validatePackagesFile(config, directory); }); - fileTest(".packages non-default name", { - "pheldagriff": packagesFile, + fileTest('.packages non-default name', { + 'pheldagriff': packagesFile, }, (Directory directory) async { - var file = dirFile(directory, "pheldagriff"); + var file = dirFile(directory, 'pheldagriff'); var config = await loadPackageConfig(file); expect(config.version, 1); validatePackagesFile(config, directory); }); - fileTest("no config found", {}, (Directory directory) { - var file = dirFile(directory, "anyname"); + fileTest('no config found', {}, (Directory directory) { + var file = dirFile(directory, 'anyname'); expect(() => loadPackageConfig(file), throwsA(TypeMatcher())); }); - fileTest("no config found, handled", {}, (Directory directory) async { - var file = dirFile(directory, "anyname"); + fileTest('no config found, handled', {}, (Directory directory) async { + var file = dirFile(directory, 'anyname'); var hadError = false; await loadPackageConfig(file, onError: expectAsync1((error) { @@ -293,31 +293,31 @@ void main() { expect(hadError, true); }); - fileTest("specified file syntax error", { - "anyname": "syntax error", + fileTest('specified file syntax error', { + 'anyname': 'syntax error', }, (Directory directory) { - var file = dirFile(directory, "anyname"); + var file = dirFile(directory, 'anyname'); expect(() => loadPackageConfig(file), throwsFormatException); }); // Find package_config.json in subdir even if initial file syntax error. - fileTest("specified file syntax onError", { - ".packages": "syntax error", - ".dart_tool": { - "package_config.json": packageConfigFile, + fileTest('specified file syntax onError', { + '.packages': 'syntax error', + '.dart_tool': { + 'package_config.json': packageConfigFile, }, }, (Directory directory) async { - var file = dirFile(directory, ".packages"); + var file = dirFile(directory, '.packages'); var config = await loadPackageConfig(file); expect(config.version, 2); validatePackagesFile(config, directory); }); // A file starting with `{` is a package_config.json file. - fileTest("file syntax error with {", { - ".packages": "{syntax error", + fileTest('file syntax error with {', { + '.packages': '{syntax error', }, (Directory directory) { - var file = dirFile(directory, ".packages"); + var file = dirFile(directory, '.packages'); expect(() => loadPackageConfig(file), throwsFormatException); }); }); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index a89527918..0a9b91720 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -5,19 +5,19 @@ @TestOn('vm') library package_config.discovery_test; -import "package:test/test.dart"; -import "package:package_config/package_config.dart"; +import 'package:test/test.dart'; +import 'package:package_config/package_config.dart'; -import "src/util.dart"; +import 'src/util.dart'; -const packagesFile = """ +const packagesFile = ''' # A comment foo:file:///dart/packages/foo/ bar:/dart/packages/bar/ baz:packages/baz/ -"""; +'''; -const packageConfigFile = """ +const packageConfigFile = ''' { "configVersion": 2, "packages": [ @@ -36,29 +36,29 @@ const packageConfigFile = """ ], "extra": [42] } -"""; +'''; void validatePackagesFile(PackageConfig resolver, Uri directory) { expect(resolver, isNotNull); - expect(resolver.resolve(pkg("foo", "bar/baz")), - equals(Uri.parse("file:///dart/packages/foo/bar/baz"))); - expect(resolver.resolve(pkg("bar", "baz/qux")), - equals(directory.resolve("/dart/packages/bar/baz/qux"))); - expect(resolver.resolve(pkg("baz", "qux/foo")), - equals(directory.resolve("packages/baz/qux/foo"))); + expect(resolver.resolve(pkg('foo', 'bar/baz')), + equals(Uri.parse('file:///dart/packages/foo/bar/baz'))); + expect(resolver.resolve(pkg('bar', 'baz/qux')), + equals(directory.resolve('/dart/packages/bar/baz/qux'))); + expect(resolver.resolve(pkg('baz', 'qux/foo')), + equals(directory.resolve('packages/baz/qux/foo'))); expect([for (var p in resolver.packages) p.name], - unorderedEquals(["foo", "bar", "baz"])); + unorderedEquals(['foo', 'bar', 'baz'])); } void main() { - group("findPackages", () { + group('findPackages', () { // Finds package_config.json if there. - loaderTest("package_config.json", { - ".packages": "invalid .packages file", - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}}, - ".dart_tool": { - "package_config.json": packageConfigFile, + loaderTest('package_config.json', { + '.packages': 'invalid .packages file', + 'script.dart': 'main(){}', + 'packages': {'shouldNotBeFound': {}}, + '.dart_tool': { + 'package_config.json': packageConfigFile, } }, (directory, loader) async { var config = (await findPackageConfigUri(directory, loader: loader))!; @@ -67,10 +67,10 @@ void main() { }); // Finds .packages if no package_config.json. - loaderTest(".packages", { - ".packages": packagesFile, - "script.dart": "main(){}", - "packages": {"shouldNotBeFound": {}} + loaderTest('.packages', { + '.packages': packagesFile, + 'script.dart': 'main(){}', + 'packages': {'shouldNotBeFound': {}} }, (directory, loader) async { var config = (await findPackageConfigUri(directory, loader: loader))!; expect(config.version, 1); // Found .packages file. @@ -78,69 +78,69 @@ void main() { }); // Finds package_config.json in super-directory. - loaderTest("package_config.json recursive", { - ".packages": packagesFile, - ".dart_tool": { - "package_config.json": packageConfigFile, + loaderTest('package_config.json recursive', { + '.packages': packagesFile, + '.dart_tool': { + 'package_config.json': packageConfigFile, }, - "subdir": { - "script.dart": "main(){}", + 'subdir': { + 'script.dart': 'main(){}', } }, (directory, loader) async { - var config = (await findPackageConfigUri(directory.resolve("subdir/"), + var config = (await findPackageConfigUri(directory.resolve('subdir/'), loader: loader))!; expect(config.version, 2); validatePackagesFile(config, directory); }); // Finds .packages in super-directory. - loaderTest(".packages recursive", { - ".packages": packagesFile, - "subdir": {"script.dart": "main(){}"} + loaderTest('.packages recursive', { + '.packages': packagesFile, + 'subdir': {'script.dart': 'main(){}'} }, (directory, loader) async { var config; - config = await findPackageConfigUri(directory.resolve("subdir/"), + config = await findPackageConfigUri(directory.resolve('subdir/'), loader: loader); expect(config.version, 1); validatePackagesFile(config, directory); }); // Does not find a packages/ directory, and returns null if nothing found. - loaderTest("package directory packages not supported", { - "packages": { - "foo": {}, + loaderTest('package directory packages not supported', { + 'packages': { + 'foo': {}, } }, (Uri directory, loader) async { var config = await findPackageConfigUri(directory, loader: loader); expect(config, null); }); - loaderTest("invalid .packages", { - ".packages": "not a .packages file", + loaderTest('invalid .packages', { + '.packages': 'not a .packages file', }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), throwsA(TypeMatcher())); }); - loaderTest("invalid .packages as JSON", { - ".packages": packageConfigFile, + loaderTest('invalid .packages as JSON', { + '.packages': packageConfigFile, }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), throwsA(TypeMatcher())); }); - loaderTest("invalid .packages", { - ".dart_tool": { - "package_config.json": "not a JSON file", + loaderTest('invalid .packages', { + '.dart_tool': { + 'package_config.json': 'not a JSON file', } }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), throwsA(TypeMatcher())); }); - loaderTest("invalid .packages as INI", { - ".dart_tool": { - "package_config.json": packagesFile, + loaderTest('invalid .packages as INI', { + '.dart_tool': { + 'package_config.json': packagesFile, } }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), @@ -148,80 +148,80 @@ void main() { }); }); - group("loadPackageConfig", () { + group('loadPackageConfig', () { // Load a specific files - group("package_config.json", () { + group('package_config.json', () { var files = { - ".packages": packagesFile, - ".dart_tool": { - "package_config.json": packageConfigFile, + '.packages': packagesFile, + '.dart_tool': { + 'package_config.json': packageConfigFile, }, }; - loaderTest("directly", files, (Uri directory, loader) async { - var file = directory.resolve(".dart_tool/package_config.json"); + loaderTest('directly', files, (Uri directory, loader) async { + var file = directory.resolve('.dart_tool/package_config.json'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); - loaderTest("indirectly through .packages", files, + loaderTest('indirectly through .packages', files, (Uri directory, loader) async { - var file = directory.resolve(".packages"); + var file = directory.resolve('.packages'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); }); - loaderTest("package_config.json non-default name", { - ".packages": packagesFile, - "subdir": { - "pheldagriff": packageConfigFile, + loaderTest('package_config.json non-default name', { + '.packages': packagesFile, + 'subdir': { + 'pheldagriff': packageConfigFile, }, }, (Uri directory, loader) async { - var file = directory.resolve("subdir/pheldagriff"); + var file = directory.resolve('subdir/pheldagriff'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); - loaderTest("package_config.json named .packages", { - "subdir": { - ".packages": packageConfigFile, + loaderTest('package_config.json named .packages', { + 'subdir': { + '.packages': packageConfigFile, }, }, (Uri directory, loader) async { - var file = directory.resolve("subdir/.packages"); + var file = directory.resolve('subdir/.packages'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 2); validatePackagesFile(config, directory); }); - loaderTest(".packages", { - ".packages": packagesFile, + loaderTest('.packages', { + '.packages': packagesFile, }, (Uri directory, loader) async { - var file = directory.resolve(".packages"); + var file = directory.resolve('.packages'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 1); validatePackagesFile(config, directory); }); - loaderTest(".packages non-default name", { - "pheldagriff": packagesFile, + loaderTest('.packages non-default name', { + 'pheldagriff': packagesFile, }, (Uri directory, loader) async { - var file = directory.resolve("pheldagriff"); + var file = directory.resolve('pheldagriff'); var config = await loadPackageConfigUri(file, loader: loader); expect(config.version, 1); validatePackagesFile(config, directory); }); - loaderTest("no config found", {}, (Uri directory, loader) { - var file = directory.resolve("anyname"); + loaderTest('no config found', {}, (Uri directory, loader) { + var file = directory.resolve('anyname'); expect(() => loadPackageConfigUri(file, loader: loader), throwsA(isA())); }); - loaderTest("no config found, handle error", {}, + loaderTest('no config found, handle error', {}, (Uri directory, loader) async { - var file = directory.resolve("anyname"); + var file = directory.resolve('anyname'); var hadError = false; await loadPackageConfigUri(file, loader: loader, @@ -232,18 +232,18 @@ void main() { expect(hadError, true); }); - loaderTest("specified file syntax error", { - "anyname": "syntax error", + loaderTest('specified file syntax error', { + 'anyname': 'syntax error', }, (Uri directory, loader) { - var file = directory.resolve("anyname"); + var file = directory.resolve('anyname'); expect(() => loadPackageConfigUri(file, loader: loader), throwsFormatException); }); - loaderTest("specified file syntax onError", { - "anyname": "syntax error", + loaderTest('specified file syntax onError', { + 'anyname': 'syntax error', }, (directory, loader) async { - var file = directory.resolve("anyname"); + var file = directory.resolve('anyname'); var hadError = false; await loadPackageConfigUri(file, loader: loader, @@ -255,22 +255,22 @@ void main() { }); // Don't look for package_config.json if original file not named .packages. - loaderTest("specified file syntax error with alternative", { - "anyname": "syntax error", - ".dart_tool": { - "package_config.json": packageConfigFile, + loaderTest('specified file syntax error with alternative', { + 'anyname': 'syntax error', + '.dart_tool': { + 'package_config.json': packageConfigFile, }, }, (directory, loader) async { - var file = directory.resolve("anyname"); + var file = directory.resolve('anyname'); expect(() => loadPackageConfigUri(file, loader: loader), throwsFormatException); }); // A file starting with `{` is a package_config.json file. - loaderTest("file syntax error with {", { - ".packages": "{syntax error", + loaderTest('file syntax error with {', { + '.packages': '{syntax error', }, (directory, loader) async { - var file = directory.resolve(".packages"); + var file = directory.resolve('.packages'); var hadError = false; await loadPackageConfigUri(file, loader: loader, diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart index bb00d1210..cef121713 100644 --- a/pkgs/package_config/test/package_config_impl_test.dart +++ b/pkgs/package_config/test/package_config_impl_test.dart @@ -2,39 +2,39 @@ // 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. -import "dart:convert" show jsonDecode; +import 'dart:convert' show jsonDecode; -import "package:package_config/package_config_types.dart"; -import "package:test/test.dart"; -import "src/util.dart"; +import 'package:package_config/package_config_types.dart'; +import 'package:test/test.dart'; +import 'src/util.dart'; void main() { var unique = Object(); - var root = Uri.file("/tmp/root/"); + var root = Uri.file('/tmp/root/'); - group("LanguageVersion", () { - test("minimal", () { + group('LanguageVersion', () { + test('minimal', () { var version = LanguageVersion(3, 5); expect(version.major, 3); expect(version.minor, 5); }); - test("negative major", () { + test('negative major', () { expect(() => LanguageVersion(-1, 1), throwsArgumentError); }); - test("negative minor", () { + test('negative minor', () { expect(() => LanguageVersion(1, -1), throwsArgumentError); }); - test("minimal parse", () { - var version = LanguageVersion.parse("3.5"); + test('minimal parse', () { + var version = LanguageVersion.parse('3.5'); expect(version.major, 3); expect(version.minor, 5); }); void failParse(String name, String input) { - test("$name - error", () { + test('$name - error', () { expect(() => LanguageVersion.parse(input), throwsA(TypeMatcher())); expect(() => LanguageVersion.parse(input), throwsFormatException); @@ -47,37 +47,37 @@ void main() { }); } - failParse("Leading zero major", "01.1"); - failParse("Leading zero minor", "1.01"); - failParse("Sign+ major", "+1.1"); - failParse("Sign- major", "-1.1"); - failParse("Sign+ minor", "1.+1"); - failParse("Sign- minor", "1.-1"); - failParse("WhiteSpace 1", " 1.1"); - failParse("WhiteSpace 2", "1 .1"); - failParse("WhiteSpace 3", "1. 1"); - failParse("WhiteSpace 4", "1.1 "); + failParse('Leading zero major', '01.1'); + failParse('Leading zero minor', '1.01'); + failParse('Sign+ major', '+1.1'); + failParse('Sign- major', '-1.1'); + failParse('Sign+ minor', '1.+1'); + failParse('Sign- minor', '1.-1'); + failParse('WhiteSpace 1', ' 1.1'); + failParse('WhiteSpace 2', '1 .1'); + failParse('WhiteSpace 3', '1. 1'); + failParse('WhiteSpace 4', '1.1 '); }); - group("Package", () { - test("minimal", () { - var package = Package("name", root, extraData: unique); - expect(package.name, "name"); + group('Package', () { + test('minimal', () { + var package = Package('name', root, extraData: unique); + expect(package.name, 'name'); expect(package.root, root); expect(package.packageUriRoot, root); expect(package.languageVersion, null); expect(package.extraData, same(unique)); }); - test("absolute package root", () { + test('absolute package root', () { var version = LanguageVersion(1, 1); - var absolute = root.resolve("foo/bar/"); - var package = Package("name", root, + var absolute = root.resolve('foo/bar/'); + var package = Package('name', root, packageUriRoot: absolute, relativeRoot: false, languageVersion: version, extraData: unique); - expect(package.name, "name"); + expect(package.name, 'name'); expect(package.root, root); expect(package.packageUriRoot, absolute); expect(package.languageVersion, version); @@ -85,12 +85,12 @@ void main() { expect(package.relativeRoot, false); }); - test("relative package root", () { - var relative = Uri.parse("foo/bar/"); + test('relative package root', () { + var relative = Uri.parse('foo/bar/'); var absolute = root.resolveUri(relative); - var package = Package("name", root, + var package = Package('name', root, packageUriRoot: relative, relativeRoot: true, extraData: unique); - expect(package.name, "name"); + expect(package.name, 'name'); expect(package.root, root); expect(package.packageUriRoot, absolute); expect(package.relativeRoot, true); @@ -98,89 +98,89 @@ void main() { expect(package.extraData, same(unique)); }); - for (var badName in ["a/z", "a:z", "", "..."]) { + for (var badName in ['a/z', 'a:z', '', '...']) { test("Invalid name '$badName'", () { expect(() => Package(badName, root), throwsPackageConfigError); }); } - test("Invalid root, not absolute", () { + test('Invalid root, not absolute', () { expect( - () => Package("name", Uri.parse("/foo/")), throwsPackageConfigError); + () => Package('name', Uri.parse('/foo/')), throwsPackageConfigError); }); - test("Invalid root, not ending in slash", () { - expect(() => Package("name", Uri.parse("file:///foo")), + test('Invalid root, not ending in slash', () { + expect(() => Package('name', Uri.parse('file:///foo')), throwsPackageConfigError); }); - test("invalid package root, not ending in slash", () { - expect(() => Package("name", root, packageUriRoot: Uri.parse("foo")), + test('invalid package root, not ending in slash', () { + expect(() => Package('name', root, packageUriRoot: Uri.parse('foo')), throwsPackageConfigError); }); - test("invalid package root, not inside root", () { - expect(() => Package("name", root, packageUriRoot: Uri.parse("../baz/")), + test('invalid package root, not inside root', () { + expect(() => Package('name', root, packageUriRoot: Uri.parse('../baz/')), throwsPackageConfigError); }); }); - group("package config", () { - test("emtpy", () { + group('package config', () { + test('emtpy', () { var empty = PackageConfig([], extraData: unique); expect(empty.version, 2); expect(empty.packages, isEmpty); expect(empty.extraData, same(unique)); - expect(empty.resolve(pkg("a", "b")), isNull); + expect(empty.resolve(pkg('a', 'b')), isNull); }); - test("single", () { - var package = Package("name", root); + test('single', () { + var package = Package('name', root); var single = PackageConfig([package], extraData: unique); expect(single.version, 2); expect(single.packages, hasLength(1)); expect(single.extraData, same(unique)); - expect(single.resolve(pkg("a", "b")), isNull); - var resolved = single.resolve(pkg("name", "a/b")); - expect(resolved, root.resolve("a/b")); + expect(single.resolve(pkg('a', 'b')), isNull); + var resolved = single.resolve(pkg('name', 'a/b')); + expect(resolved, root.resolve('a/b')); }); }); - test("writeString", () { + test('writeString', () { var config = PackageConfig([ - Package("foo", Uri.parse("file:///pkg/foo/"), - packageUriRoot: Uri.parse("file:///pkg/foo/lib/"), + Package('foo', Uri.parse('file:///pkg/foo/'), + packageUriRoot: Uri.parse('file:///pkg/foo/lib/'), relativeRoot: false, languageVersion: LanguageVersion(2, 4), - extraData: {"foo": "foo!"}), - Package("bar", Uri.parse("file:///pkg/bar/"), - packageUriRoot: Uri.parse("file:///pkg/bar/lib/"), + extraData: {'foo': 'foo!'}), + Package('bar', Uri.parse('file:///pkg/bar/'), + packageUriRoot: Uri.parse('file:///pkg/bar/lib/'), relativeRoot: true, - extraData: {"bar": "bar!"}), + extraData: {'bar': 'bar!'}), ], extraData: { - "extra": "data" + 'extra': 'data' }); var buffer = StringBuffer(); - PackageConfig.writeString(config, buffer, Uri.parse("file:///pkg/")); + PackageConfig.writeString(config, buffer, Uri.parse('file:///pkg/')); var text = buffer.toString(); var json = jsonDecode(text); // Is valid JSON. expect(json, { - "configVersion": 2, - "packages": unorderedEquals([ + 'configVersion': 2, + 'packages': unorderedEquals([ { - "name": "foo", - "rootUri": "file:///pkg/foo/", - "packageUri": "lib/", - "languageVersion": "2.4", - "foo": "foo!", + 'name': 'foo', + 'rootUri': 'file:///pkg/foo/', + 'packageUri': 'lib/', + 'languageVersion': '2.4', + 'foo': 'foo!', }, { - "name": "bar", - "rootUri": "bar/", - "packageUri": "lib/", - "bar": "bar!", + 'name': 'bar', + 'rootUri': 'bar/', + 'packageUri': 'lib/', + 'bar': 'bar!', }, ]), - "extra": "data", + 'extra': 'data', }); }); } diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index ef73c2e1e..a163e127f 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -2,61 +2,61 @@ // 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. -import "dart:convert"; +import 'dart:convert'; import 'dart:typed_data'; -import "package:test/test.dart"; +import 'package:test/test.dart'; -import "package:package_config/package_config_types.dart"; -import "package:package_config/src/packages_file.dart" as packages; -import "package:package_config/src/package_config_json.dart"; -import "src/util.dart"; +import 'package:package_config/package_config_types.dart'; +import 'package:package_config/src/packages_file.dart' as packages; +import 'package:package_config/src/package_config_json.dart'; +import 'src/util.dart'; void throwError(Object error) => throw error; void main() { - group(".packages", () { - test("valid", () { - var packagesFile = "# Generated by pub yadda yadda\n" - "foo:file:///foo/lib/\n" - "bar:/bar/lib/\n" - "baz:lib/\n"; + group('.packages', () { + test('valid', () { + var packagesFile = '# Generated by pub yadda yadda\n' + 'foo:file:///foo/lib/\n' + 'bar:/bar/lib/\n' + 'baz:lib/\n'; var result = packages.parse(utf8.encode(packagesFile), - Uri.parse("file:///tmp/file.dart"), throwError); + Uri.parse('file:///tmp/file.dart'), throwError); expect(result.version, 1); - expect({for (var p in result.packages) p.name}, {"foo", "bar", "baz"}); - expect(result.resolve(pkg("foo", "foo.dart")), - Uri.parse("file:///foo/lib/foo.dart")); - expect(result.resolve(pkg("bar", "bar.dart")), - Uri.parse("file:///bar/lib/bar.dart")); - expect(result.resolve(pkg("baz", "baz.dart")), - Uri.parse("file:///tmp/lib/baz.dart")); + expect({for (var p in result.packages) p.name}, {'foo', 'bar', 'baz'}); + expect(result.resolve(pkg('foo', 'foo.dart')), + Uri.parse('file:///foo/lib/foo.dart')); + expect(result.resolve(pkg('bar', 'bar.dart')), + Uri.parse('file:///bar/lib/bar.dart')); + expect(result.resolve(pkg('baz', 'baz.dart')), + Uri.parse('file:///tmp/lib/baz.dart')); - var foo = result["foo"]!; + var foo = result['foo']!; expect(foo, isNotNull); - expect(foo.root, Uri.parse("file:///foo/")); - expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); + expect(foo.root, Uri.parse('file:///foo/')); + expect(foo.packageUriRoot, Uri.parse('file:///foo/lib/')); expect(foo.languageVersion, LanguageVersion(2, 7)); expect(foo.relativeRoot, false); }); - test("valid empty", () { - var packagesFile = "# Generated by pub yadda yadda\n"; + test('valid empty', () { + var packagesFile = '# Generated by pub yadda yadda\n'; var result = packages.parse( - utf8.encode(packagesFile), Uri.file("/tmp/file.dart"), throwError); + utf8.encode(packagesFile), Uri.file('/tmp/file.dart'), throwError); expect(result.version, 1); expect({for (var p in result.packages) p.name}, {}); }); - group("invalid", () { - var baseFile = Uri.file("/tmp/file.dart"); + group('invalid', () { + var baseFile = Uri.file('/tmp/file.dart'); void testThrows(String name, String content) { test(name, () { expect( () => packages.parse(utf8.encode(content), baseFile, throwError), throwsA(TypeMatcher())); }); - test(name + ", handle error", () { + test(name + ', handle error', () { var hadError = false; packages.parse(utf8.encode(content), baseFile, (error) { hadError = true; @@ -66,21 +66,21 @@ void main() { }); } - testThrows("repeated package name", "foo:lib/\nfoo:lib\n"); - testThrows("no colon", "foo\n"); - testThrows("empty package name", ":lib/\n"); - testThrows("dot only package name", ".:lib/\n"); - testThrows("dot only package name", "..:lib/\n"); - testThrows("invalid package name character", "f\\o:lib/\n"); - testThrows("package URI", "foo:package:bar/lib/"); - testThrows("location with query", "f\\o:lib/?\n"); - testThrows("location with fragment", "f\\o:lib/#\n"); + testThrows('repeated package name', 'foo:lib/\nfoo:lib\n'); + testThrows('no colon', 'foo\n'); + testThrows('empty package name', ':lib/\n'); + testThrows('dot only package name', '.:lib/\n'); + testThrows('dot only package name', '..:lib/\n'); + testThrows('invalid package name character', 'f\\o:lib/\n'); + testThrows('package URI', 'foo:package:bar/lib/'); + testThrows('location with query', 'f\\o:lib/?\n'); + testThrows('location with fragment', 'f\\o:lib/#\n'); }); }); - group("package_config.json", () { - test("valid", () { - var packageConfigFile = """ + group('package_config.json', () { + test('valid', () { + var packageConfigFile = ''' { "configVersion": 2, "packages": [ @@ -111,62 +111,62 @@ void main() { "generator": "pub", "other": [42] } - """; + '''; var config = parsePackageConfigBytes( utf8.encode(packageConfigFile) as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); expect({for (var p in config.packages) p.name}, - {"foo", "bar", "baz", "noslash"}); + {'foo', 'bar', 'baz', 'noslash'}); - expect(config.resolve(pkg("foo", "foo.dart")), - Uri.parse("file:///foo/lib/foo.dart")); - expect(config.resolve(pkg("bar", "bar.dart")), - Uri.parse("file:///bar/lib/bar.dart")); - expect(config.resolve(pkg("baz", "baz.dart")), - Uri.parse("file:///tmp/lib/baz.dart")); + expect(config.resolve(pkg('foo', 'foo.dart')), + Uri.parse('file:///foo/lib/foo.dart')); + expect(config.resolve(pkg('bar', 'bar.dart')), + Uri.parse('file:///bar/lib/bar.dart')); + expect(config.resolve(pkg('baz', 'baz.dart')), + Uri.parse('file:///tmp/lib/baz.dart')); - var foo = config["foo"]!; + var foo = config['foo']!; expect(foo, isNotNull); - expect(foo.root, Uri.parse("file:///foo/")); - expect(foo.packageUriRoot, Uri.parse("file:///foo/lib/")); + expect(foo.root, Uri.parse('file:///foo/')); + expect(foo.packageUriRoot, Uri.parse('file:///foo/lib/')); expect(foo.languageVersion, LanguageVersion(2, 5)); - expect(foo.extraData, {"nonstandard": true}); + expect(foo.extraData, {'nonstandard': true}); expect(foo.relativeRoot, false); - var bar = config["bar"]!; + var bar = config['bar']!; expect(bar, isNotNull); - expect(bar.root, Uri.parse("file:///bar/")); - expect(bar.packageUriRoot, Uri.parse("file:///bar/lib/")); + expect(bar.root, Uri.parse('file:///bar/')); + expect(bar.packageUriRoot, Uri.parse('file:///bar/lib/')); expect(bar.languageVersion, LanguageVersion(9999, 9999)); expect(bar.extraData, null); expect(bar.relativeRoot, false); - var baz = config["baz"]!; + var baz = config['baz']!; expect(baz, isNotNull); - expect(baz.root, Uri.parse("file:///tmp/")); - expect(baz.packageUriRoot, Uri.parse("file:///tmp/lib/")); + expect(baz.root, Uri.parse('file:///tmp/')); + expect(baz.packageUriRoot, Uri.parse('file:///tmp/lib/')); expect(baz.languageVersion, null); expect(baz.relativeRoot, true); // No slash after root or package root. One is inserted. - var noslash = config["noslash"]!; + var noslash = config['noslash']!; expect(noslash, isNotNull); - expect(noslash.root, Uri.parse("file:///tmp/noslash/")); - expect(noslash.packageUriRoot, Uri.parse("file:///tmp/noslash/lib/")); + expect(noslash.root, Uri.parse('file:///tmp/noslash/')); + expect(noslash.packageUriRoot, Uri.parse('file:///tmp/noslash/lib/')); expect(noslash.languageVersion, null); expect(noslash.relativeRoot, true); expect(config.extraData, { - "generator": "pub", - "other": [42] + 'generator': 'pub', + 'other': [42] }); }); - test("valid other order", () { + test('valid other order', () { // The ordering in the file is not important. - var packageConfigFile = """ + var packageConfigFile = ''' { "generator": "pub", "other": [42], @@ -191,23 +191,23 @@ void main() { ], "configVersion": 2 } - """; + '''; var config = parsePackageConfigBytes( utf8.encode(packageConfigFile) as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); - expect({for (var p in config.packages) p.name}, {"foo", "bar", "baz"}); + expect({for (var p in config.packages) p.name}, {'foo', 'bar', 'baz'}); - expect(config.resolve(pkg("foo", "foo.dart")), - Uri.parse("file:///foo/lib/foo.dart")); - expect(config.resolve(pkg("bar", "bar.dart")), - Uri.parse("file:///bar/lib/bar.dart")); - expect(config.resolve(pkg("baz", "baz.dart")), - Uri.parse("file:///tmp/lib/baz.dart")); + expect(config.resolve(pkg('foo', 'foo.dart')), + Uri.parse('file:///foo/lib/foo.dart')); + expect(config.resolve(pkg('bar', 'bar.dart')), + Uri.parse('file:///bar/lib/bar.dart')); + expect(config.resolve(pkg('baz', 'baz.dart')), + Uri.parse('file:///tmp/lib/baz.dart')); expect(config.extraData, { - "generator": "pub", - "other": [42] + 'generator': 'pub', + 'other': [42] }); }); @@ -217,94 +217,94 @@ void main() { var pkgs = '"packages":[]'; var name = '"name":"foo"'; var root = '"rootUri":"/foo/"'; - test("minimal", () { + test('minimal', () { var config = parsePackageConfigBytes( - utf8.encode("{$cfg,$pkgs}") as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), + utf8.encode('{$cfg,$pkgs}') as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); expect(config.packages, isEmpty); }); - test("minimal package", () { + test('minimal package', () { // A package must have a name and a rootUri, the remaining properties // are optional. var config = parsePackageConfigBytes( utf8.encode('{$cfg,"packages":[{$name,$root}]}') as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); - expect(config.packages.first.name, "foo"); + expect(config.packages.first.name, 'foo'); }); - test("nested packages", () { + test('nested packages', () { var configBytes = utf8.encode(json.encode({ - "configVersion": 2, - "packages": [ - {"name": "foo", "rootUri": "/foo/", "packageUri": "lib/"}, - {"name": "bar", "rootUri": "/foo/bar/", "packageUri": "lib/"}, - {"name": "baz", "rootUri": "/foo/bar/baz/", "packageUri": "lib/"}, - {"name": "qux", "rootUri": "/foo/qux/", "packageUri": "lib/"}, + 'configVersion': 2, + 'packages': [ + {'name': 'foo', 'rootUri': '/foo/', 'packageUri': 'lib/'}, + {'name': 'bar', 'rootUri': '/foo/bar/', 'packageUri': 'lib/'}, + {'name': 'baz', 'rootUri': '/foo/bar/baz/', 'packageUri': 'lib/'}, + {'name': 'qux', 'rootUri': '/foo/qux/', 'packageUri': 'lib/'}, ] })); var config = parsePackageConfigBytes(configBytes as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError); + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); - expect(config.packageOf(Uri.parse("file:///foo/lala/lala.dart"))!.name, - "foo"); - expect(config.packageOf(Uri.parse("file:///foo/bar/lala.dart"))!.name, - "bar"); - expect(config.packageOf(Uri.parse("file:///foo/bar/baz/lala.dart"))!.name, - "baz"); - expect(config.packageOf(Uri.parse("file:///foo/qux/lala.dart"))!.name, - "qux"); - expect(config.toPackageUri(Uri.parse("file:///foo/lib/diz")), - Uri.parse("package:foo/diz")); - expect(config.toPackageUri(Uri.parse("file:///foo/bar/lib/diz")), - Uri.parse("package:bar/diz")); - expect(config.toPackageUri(Uri.parse("file:///foo/bar/baz/lib/diz")), - Uri.parse("package:baz/diz")); - expect(config.toPackageUri(Uri.parse("file:///foo/qux/lib/diz")), - Uri.parse("package:qux/diz")); + expect(config.packageOf(Uri.parse('file:///foo/lala/lala.dart'))!.name, + 'foo'); + expect(config.packageOf(Uri.parse('file:///foo/bar/lala.dart'))!.name, + 'bar'); + expect(config.packageOf(Uri.parse('file:///foo/bar/baz/lala.dart'))!.name, + 'baz'); + expect(config.packageOf(Uri.parse('file:///foo/qux/lala.dart'))!.name, + 'qux'); + expect(config.toPackageUri(Uri.parse('file:///foo/lib/diz')), + Uri.parse('package:foo/diz')); + expect(config.toPackageUri(Uri.parse('file:///foo/bar/lib/diz')), + Uri.parse('package:bar/diz')); + expect(config.toPackageUri(Uri.parse('file:///foo/bar/baz/lib/diz')), + Uri.parse('package:baz/diz')); + expect(config.toPackageUri(Uri.parse('file:///foo/qux/lib/diz')), + Uri.parse('package:qux/diz')); }); - group("invalid", () { + group('invalid', () { void testThrows(String name, String source) { test(name, () { expect( () => parsePackageConfigBytes(utf8.encode(source) as Uint8List, - Uri.parse("file:///tmp/.dart_tool/file.dart"), throwError), + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError), throwsA(TypeMatcher())); }); } - testThrows("comment", '# comment\n {$cfg,$pkgs}'); - testThrows(".packages file", 'foo:/foo\n'); - testThrows("no configVersion", '{$pkgs}'); - testThrows("no packages", '{$cfg}'); - group("config version:", () { - testThrows("null", '{"configVersion":null,$pkgs}'); - testThrows("string", '{"configVersion":"2",$pkgs}'); - testThrows("array", '{"configVersion":[2],$pkgs}'); + testThrows('comment', '# comment\n {$cfg,$pkgs}'); + testThrows('.packages file', 'foo:/foo\n'); + testThrows('no configVersion', '{$pkgs}'); + testThrows('no packages', '{$cfg}'); + group('config version:', () { + testThrows('null', '{"configVersion":null,$pkgs}'); + testThrows('string', '{"configVersion":"2",$pkgs}'); + testThrows('array', '{"configVersion":[2],$pkgs}'); }); - group("packages:", () { - testThrows("null", '{$cfg,"packages":null}'); - testThrows("string", '{$cfg,"packages":"foo"}'); - testThrows("object", '{$cfg,"packages":{}}'); + group('packages:', () { + testThrows('null', '{$cfg,"packages":null}'); + testThrows('string', '{$cfg,"packages":"foo"}'); + testThrows('object', '{$cfg,"packages":{}}'); }); - group("packages entry:", () { - testThrows("null", '{$cfg,"packages":[null]}'); - testThrows("string", '{$cfg,"packages":["foo"]}'); - testThrows("array", '{$cfg,"packages":[[]]}'); + group('packages entry:', () { + testThrows('null', '{$cfg,"packages":[null]}'); + testThrows('string', '{$cfg,"packages":["foo"]}'); + testThrows('array', '{$cfg,"packages":[[]]}'); }); - group("package", () { - testThrows("no name", '{$cfg,"packages":[{$root}]}'); - group("name:", () { - testThrows("null", '{$cfg,"packages":[{"name":null,$root}]}'); - testThrows("num", '{$cfg,"packages":[{"name":1,$root}]}'); - testThrows("object", '{$cfg,"packages":[{"name":{},$root}]}'); - testThrows("empty", '{$cfg,"packages":[{"name":"",$root}]}'); - testThrows("one-dot", '{$cfg,"packages":[{"name":".",$root}]}'); - testThrows("two-dot", '{$cfg,"packages":[{"name":"..",$root}]}'); + group('package', () { + testThrows('no name', '{$cfg,"packages":[{$root}]}'); + group('name:', () { + testThrows('null', '{$cfg,"packages":[{"name":null,$root}]}'); + testThrows('num', '{$cfg,"packages":[{"name":1,$root}]}'); + testThrows('object', '{$cfg,"packages":[{"name":{},$root}]}'); + testThrows('empty', '{$cfg,"packages":[{"name":"",$root}]}'); + testThrows('one-dot', '{$cfg,"packages":[{"name":".",$root}]}'); + testThrows('two-dot', '{$cfg,"packages":[{"name":"..",$root}]}'); testThrows( "invalid char '\\'", '{$cfg,"packages":[{"name":"\\",$root}]}'); testThrows( @@ -313,82 +313,82 @@ void main() { "invalid char ' '", '{$cfg,"packages":[{"name":" ",$root}]}'); }); - testThrows("no root", '{$cfg,"packages":[{$name}]}'); - group("root:", () { - testThrows("null", '{$cfg,"packages":[{$name,"rootUri":null}]}'); - testThrows("num", '{$cfg,"packages":[{$name,"rootUri":1}]}'); - testThrows("object", '{$cfg,"packages":[{$name,"rootUri":{}}]}'); - testThrows("fragment", '{$cfg,"packages":[{$name,"rootUri":"x/#"}]}'); - testThrows("query", '{$cfg,"packages":[{$name,"rootUri":"x/?"}]}'); - testThrows("package-URI", + testThrows('no root', '{$cfg,"packages":[{$name}]}'); + group('root:', () { + testThrows('null', '{$cfg,"packages":[{$name,"rootUri":null}]}'); + testThrows('num', '{$cfg,"packages":[{$name,"rootUri":1}]}'); + testThrows('object', '{$cfg,"packages":[{$name,"rootUri":{}}]}'); + testThrows('fragment', '{$cfg,"packages":[{$name,"rootUri":"x/#"}]}'); + testThrows('query', '{$cfg,"packages":[{$name,"rootUri":"x/?"}]}'); + testThrows('package-URI', '{$cfg,"packages":[{$name,"rootUri":"package:x/x/"}]}'); }); - group("package-URI root:", () { + group('package-URI root:', () { testThrows( - "null", '{$cfg,"packages":[{$name,$root,"packageUri":null}]}'); - testThrows("num", '{$cfg,"packages":[{$name,$root,"packageUri":1}]}'); + 'null', '{$cfg,"packages":[{$name,$root,"packageUri":null}]}'); + testThrows('num', '{$cfg,"packages":[{$name,$root,"packageUri":1}]}'); testThrows( - "object", '{$cfg,"packages":[{$name,$root,"packageUri":{}}]}'); - testThrows("fragment", + 'object', '{$cfg,"packages":[{$name,$root,"packageUri":{}}]}'); + testThrows('fragment', '{$cfg,"packages":[{$name,$root,"packageUri":"x/#"}]}'); testThrows( - "query", '{$cfg,"packages":[{$name,$root,"packageUri":"x/?"}]}'); - testThrows("package: URI", + 'query', '{$cfg,"packages":[{$name,$root,"packageUri":"x/?"}]}'); + testThrows('package: URI', '{$cfg,"packages":[{$name,$root,"packageUri":"package:x/x/"}]}'); - testThrows("not inside root", + testThrows('not inside root', '{$cfg,"packages":[{$name,$root,"packageUri":"../other/"}]}'); }); - group("language version", () { - testThrows("null", + group('language version', () { + testThrows('null', '{$cfg,"packages":[{$name,$root,"languageVersion":null}]}'); testThrows( - "num", '{$cfg,"packages":[{$name,$root,"languageVersion":1}]}'); - testThrows("object", + 'num', '{$cfg,"packages":[{$name,$root,"languageVersion":1}]}'); + testThrows('object', '{$cfg,"packages":[{$name,$root,"languageVersion":{}}]}'); - testThrows("empty", + testThrows('empty', '{$cfg,"packages":[{$name,$root,"languageVersion":""}]}'); - testThrows("non number.number", + testThrows('non number.number', '{$cfg,"packages":[{$name,$root,"languageVersion":"x.1"}]}'); - testThrows("number.non number", + testThrows('number.non number', '{$cfg,"packages":[{$name,$root,"languageVersion":"1.x"}]}'); - testThrows("non number", + testThrows('non number', '{$cfg,"packages":[{$name,$root,"languageVersion":"x"}]}'); - testThrows("one number", + testThrows('one number', '{$cfg,"packages":[{$name,$root,"languageVersion":"1"}]}'); - testThrows("three numbers", + testThrows('three numbers', '{$cfg,"packages":[{$name,$root,"languageVersion":"1.2.3"}]}'); - testThrows("leading zero first", + testThrows('leading zero first', '{$cfg,"packages":[{$name,$root,"languageVersion":"01.1"}]}'); - testThrows("leading zero second", + testThrows('leading zero second', '{$cfg,"packages":[{$name,$root,"languageVersion":"1.01"}]}'); - testThrows("trailing-", + testThrows('trailing-', '{$cfg,"packages":[{$name,$root,"languageVersion":"1.1-1"}]}'); - testThrows("trailing+", + testThrows('trailing+', '{$cfg,"packages":[{$name,$root,"languageVersion":"1.1+1"}]}'); }); }); - testThrows("duplicate package name", + testThrows('duplicate package name', '{$cfg,"packages":[{$name,$root},{$name,"rootUri":"/other/"}]}'); - testThrows("same roots", + testThrows('same roots', '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); testThrows( // The roots of foo and bar are the same. - "same roots", + 'same roots', '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); testThrows( // The root of bar is inside the root of foo, // but the package root of foo is inside the root of bar. - "between root and lib", + 'between root and lib', '{$cfg,"packages":[' '{"name":"foo","rootUri":"/foo/","packageUri":"bar/lib/"},' '{"name":"bar","rootUri":"/foo/bar/"},"packageUri":"baz/lib"]}'); }); }); - group("factories", () { + group('factories', () { void testConfig(String name, PackageConfig config, PackageConfig expected) { group(name, () { - test("structure", () { + test('structure', () { expect(config.version, expected.version); var expectedPackages = {for (var p in expected.packages) p.name}; var actualPackages = {for (var p in config.packages) p.name}; @@ -396,20 +396,20 @@ void main() { }); for (var package in config.packages) { var name = package.name; - test("package $name", () { + test('package $name', () { var expectedPackage = expected[name]!; expect(expectedPackage, isNotNull); - expect(package.root, expectedPackage.root, reason: "root"); + expect(package.root, expectedPackage.root, reason: 'root'); expect(package.packageUriRoot, expectedPackage.packageUriRoot, - reason: "package root"); + reason: 'package root'); expect(package.languageVersion, expectedPackage.languageVersion, - reason: "languageVersion"); + reason: 'languageVersion'); }); } }); } - var configText = """ + var configText = ''' {"configVersion": 2, "packages": [ { "name": "foo", @@ -418,37 +418,37 @@ void main() { "languageVersion": "1.2" } ]} - """; - var baseUri = Uri.parse("file:///start/"); + '''; + var baseUri = Uri.parse('file:///start/'); var config = PackageConfig([ - Package("foo", Uri.parse("file:///start/foo/"), - packageUriRoot: Uri.parse("file:///start/foo/bar/"), + Package('foo', Uri.parse('file:///start/foo/'), + packageUriRoot: Uri.parse('file:///start/foo/bar/'), languageVersion: LanguageVersion(1, 2)) ]); testConfig( - "string", PackageConfig.parseString(configText, baseUri), config); + 'string', PackageConfig.parseString(configText, baseUri), config); testConfig( - "bytes", + 'bytes', PackageConfig.parseBytes( Uint8List.fromList(configText.codeUnits), baseUri), config); - testConfig("json", PackageConfig.parseJson(jsonDecode(configText), baseUri), + testConfig('json', PackageConfig.parseJson(jsonDecode(configText), baseUri), config); - baseUri = Uri.parse("file:///start2/"); + baseUri = Uri.parse('file:///start2/'); config = PackageConfig([ - Package("foo", Uri.parse("file:///start2/foo/"), - packageUriRoot: Uri.parse("file:///start2/foo/bar/"), + Package('foo', Uri.parse('file:///start2/foo/'), + packageUriRoot: Uri.parse('file:///start2/foo/bar/'), languageVersion: LanguageVersion(1, 2)) ]); testConfig( - "string2", PackageConfig.parseString(configText, baseUri), config); + 'string2', PackageConfig.parseString(configText, baseUri), config); testConfig( - "bytes2", + 'bytes2', PackageConfig.parseBytes( Uint8List.fromList(configText.codeUnits), baseUri), config); - testConfig("json2", + testConfig('json2', PackageConfig.parseJson(jsonDecode(configText), baseUri), config); }); } diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 2b262e1b2..32e92174c 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -5,13 +5,13 @@ import 'dart:convert'; import 'dart:typed_data'; -import "package:test/test.dart"; +import 'package:test/test.dart'; /// Creates a package: URI. Uri pkg(String packageName, String packagePath) { var path = "$packageName${packagePath.startsWith('/') ? "" : "/"}$packagePath"; - return Uri(scheme: "package", path: path); + return Uri(scheme: 'package', path: path); } // Remove if not used. @@ -33,13 +33,16 @@ ${packages.map((nu) => """ /// Description is a map, each key is a file entry. If the value is a map, /// it's a subdirectory, otherwise it's a file and the value is the content /// as a string. -void loaderTest(String name, Map description, - void loaderTest(Uri root, Future loader(Uri uri))) { - var root = Uri(scheme: "test", path: "/"); +void loaderTest( + String name, + Map description, + void Function(Uri root, Future Function(Uri) loader) loaderTest, +) { + var root = Uri(scheme: 'test', path: '/'); Future loader(Uri uri) async { var path = uri.path; - if (!uri.isScheme("test") || !path.startsWith("/")) return null; - var parts = path.split("/"); + if (!uri.isScheme('test') || !path.startsWith('/')) return null; + var parts = path.split('/'); Object? value = description; for (var i = 1; i < parts.length; i++) { if (value is! Map) return null; diff --git a/pkgs/package_config/test/src/util_io.dart b/pkgs/package_config/test/src/util_io.dart index 37deee9e1..109dff112 100644 --- a/pkgs/package_config/test/src/util_io.dart +++ b/pkgs/package_config/test/src/util_io.dart @@ -2,10 +2,10 @@ // 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. -import "dart:io"; +import 'dart:io'; -import "package:test/test.dart"; -import "package:package_config/src/util_io.dart"; +import 'package:test/test.dart'; +import 'package:package_config/src/util_io.dart'; /// Creates a directory structure from [description] and runs [fileTest]. /// @@ -14,9 +14,9 @@ import "package:package_config/src/util_io.dart"; /// as a string. /// Introduces a group to hold the [setUp]/[tearDown] logic. void fileTest(String name, Map description, - void fileTest(Directory directory)) { - group("file-test", () { - var tempDir = Directory.systemTemp.createTempSync("pkgcfgtest"); + void Function(Directory directory) fileTest) { + group('file-test', () { + var tempDir = Directory.systemTemp.createTempSync('pkgcfgtest'); setUp(() { _createFiles(tempDir, description); }); @@ -44,7 +44,7 @@ void fileTest(String name, Map description, // Creates temporary files in the target directory. void _createFiles(Directory target, Map description) { description.forEach((name, content) { - var entryName = pathJoin(target.path, "$name"); + var entryName = pathJoin(target.path, '$name'); if (content is Map) { _createFiles(Directory(entryName)..createSync(), content); } else { @@ -55,7 +55,7 @@ void _createFiles(Directory target, Map description) { /// Creates a [Directory] for a subdirectory of [parent]. Directory subdir(Directory parent, String dirName) => - Directory(pathJoinAll([parent.path, ...dirName.split("/")])); + Directory(pathJoinAll([parent.path, ...dirName.split('/')])); /// Creates a [File] for an entry in the [directory] directory. File dirFile(Directory directory, String fileName) => From 028521a02f773c2ef8841eee3dd9d8c4e83bb25b Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Mon, 2 Aug 2021 15:56:51 +0100 Subject: [PATCH 180/281] Fix typo: "packjage_config" (dart-lang/package_config#113) --- pkgs/package_config/lib/src/package_config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 8210132a1..3c5cc5196 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -204,7 +204,7 @@ abstract class PackageConfig { /// Extra data associated with the package configuration. /// /// The data may be in any format, depending on who introduced it. - /// The standard `packjage_config.json` file storage will only store + /// The standard `package_config.json` file storage will only store /// JSON-like list/map data structures. Object? get extraData; } From 0061cdb33d393d3732ff897c1e6d10911369d927 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Aug 2021 00:57:55 -0700 Subject: [PATCH 181/281] Ignore unnecessary casts from utf8.encode (dart-lang/package_config#114) An upcoming SDK change will change the return type to `Uint8List` which makes the casts unnecessary and introduces analyzer diagnostics. Preemptively ignore these to make it easier to roll the SDK. https://dart-review.googlesource.com/c/sdk/+/208190 --- pkgs/package_config/CHANGELOG.md | 2 ++ pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/parse_test.dart | 6 ++++++ pkgs/package_config/test/src/util.dart | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 9949b51db..898ebc4bb 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.0.2-dev + ## 2.0.1 - Use unique library names to correct docs issue. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 687c3d303..5cc9cc0a5 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.1 +version: 2.0.2-dev description: Support for working with Package Configuration files. homepage: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index a163e127f..d5c2e7268 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -113,6 +113,7 @@ void main() { } '''; var config = parsePackageConfigBytes( + // ignore: unnecessary_cast utf8.encode(packageConfigFile) as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); @@ -193,6 +194,7 @@ void main() { } '''; var config = parsePackageConfigBytes( + // ignore: unnecessary_cast utf8.encode(packageConfigFile) as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); @@ -219,6 +221,7 @@ void main() { var root = '"rootUri":"/foo/"'; test('minimal', () { var config = parsePackageConfigBytes( + // ignore: unnecessary_cast utf8.encode('{$cfg,$pkgs}') as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); @@ -229,6 +232,7 @@ void main() { // A package must have a name and a rootUri, the remaining properties // are optional. var config = parsePackageConfigBytes( + // ignore: unnecessary_cast utf8.encode('{$cfg,"packages":[{$name,$root}]}') as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); @@ -246,6 +250,7 @@ void main() { {'name': 'qux', 'rootUri': '/foo/qux/', 'packageUri': 'lib/'}, ] })); + // ignore: unnecessary_cast var config = parsePackageConfigBytes(configBytes as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); expect(config.version, 2); @@ -271,6 +276,7 @@ void main() { void testThrows(String name, String source) { test(name, () { expect( + // ignore: unnecessary_cast () => parsePackageConfigBytes(utf8.encode(source) as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError), throwsA(TypeMatcher())); diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 32e92174c..246e12964 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -48,6 +48,7 @@ void loaderTest( if (value is! Map) return null; value = value[parts[i]]; } + // ignore: unnecessary_cast if (value is String) return utf8.encode(value) as Uint8List; return null; } From c1531e295d5a64c2740a805842a52ed7e2f8fd8f Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 14:06:47 +0200 Subject: [PATCH 182/281] Switch to package:lints --- pkgs/package_config/analysis_options.yaml | 2 +- pkgs/package_config/lib/src/package_config_json.dart | 4 ++-- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 3 +-- pkgs/package_config/test/discovery_uri_test.dart | 5 ++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml index a0ba68de2..278ec4868 100644 --- a/pkgs/package_config/analysis_options.yaml +++ b/pkgs/package_config/analysis_options.yaml @@ -2,4 +2,4 @@ # 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. -include: package:pedantic/analysis_options.1.9.0.yaml +include: package:lints/recommended.yaml diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 1998b6606..fe185a2ea 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -35,7 +35,7 @@ final _jsonUtf8Decoder = json.fuse(utf8).decoder; PackageConfig parsePackageConfigBytes( Uint8List bytes, Uri file, void Function(Object error) onError) { // TODO(lrn): Make this simpler. Maybe parse directly from bytes. - var jsonObject; + Object? jsonObject; try { jsonObject = _jsonUtf8Decoder.convert(bytes); } on FormatException catch (e) { @@ -47,7 +47,7 @@ PackageConfig parsePackageConfigBytes( PackageConfig parsePackageConfigString( String source, Uri file, void Function(Object error) onError) { - var jsonObject; + Object? jsonObject; try { jsonObject = jsonDecode(source); } on FormatException catch (e) { diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5cc9cc0a5..e7c9a0a3a 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -13,5 +13,5 @@ dev_dependencies: build_runner: ^2.0.0 build_test: ^2.1.2 build_web_compilers: ^3.0.0 - pedantic: ^1.10.0 + lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index d2c3d8330..4a1bba0a6 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -99,8 +99,7 @@ void main() { '.packages': packagesFile, 'subdir': {'script.dart': 'main(){}'} }, (Directory directory) async { - var config; - config = await findPackageConfig(subdir(directory, 'subdir/')); + var config = (await findPackageConfig(subdir(directory, 'subdir/')))!; expect(config.version, 1); validatePackagesFile(config, directory); }); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 0a9b91720..e487e471d 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -98,9 +98,8 @@ void main() { '.packages': packagesFile, 'subdir': {'script.dart': 'main(){}'} }, (directory, loader) async { - var config; - config = await findPackageConfigUri(directory.resolve('subdir/'), - loader: loader); + var config = (await findPackageConfigUri(directory.resolve('subdir/'), + loader: loader))!; expect(config.version, 1); validatePackagesFile(config, directory); }); From 89cfab15a5bf72b9d8d04dc70f237392eaff4dfc Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 14:32:57 +0200 Subject: [PATCH 183/281] Update description --- pkgs/package_config/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index e7c9a0a3a..6f80473c9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,6 +1,6 @@ name: package_config -version: 2.0.2-dev -description: Support for working with Package Configuration files. +version: 2.0.2 +description: Support for reading and writing Dart Package Configuration files. homepage: https://github.com/dart-lang/package_config environment: From 8d518f7a0ec94304c35c673f775948099d63c1ac Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 14:33:03 +0200 Subject: [PATCH 184/281] Add example --- pkgs/package_config/example/main.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 pkgs/package_config/example/main.dart diff --git a/pkgs/package_config/example/main.dart b/pkgs/package_config/example/main.dart new file mode 100644 index 000000000..42a596375 --- /dev/null +++ b/pkgs/package_config/example/main.dart @@ -0,0 +1,18 @@ +// Copyright (c) 2020, 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. + +import 'package:package_config/package_config.dart'; +import 'dart:io' show Directory; + +void main() async { + var packageConfig = await findPackageConfig(Directory.current); + if (packageConfig == null) { + print('Failed to locate or read package config.'); + } else { + print('This package depends on ${packageConfig.packages.length} packages:'); + for (var package in packageConfig.packages) { + print('- ${package.name}'); + } + } +} From 9b60f7b3b70179036251993cec28e418e68f894b Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 14:37:50 +0200 Subject: [PATCH 185/281] Expand readme --- pkgs/package_config/CHANGELOG.md | 6 +++++- pkgs/package_config/README.md | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 898ebc4bb..c85ac5011 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,4 +1,8 @@ -## 2.0.2-dev +## 2.0.2 + +- Update package description and README. +- Change to package:lints for style checking. +- Add an example. ## 2.0.1 diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index ada1bd0ec..15ed4f6b2 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -4,7 +4,13 @@ Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). -The primary libraries are +A Dart package configuration file is used to resolve Dart package names (e.g. +`foobar`) to Dart files containing the source code for that package (e.g. +`file:///Users/myuser/.pub-cache/hosted/pub.dartlang.org/foobar-1.1.0`). The +standard package configuration file is `.dart_tool/package_config.json`, and is +written by the Dart tool when the command `dart pub get` is run. + +The primary libraries of this package are * `package_config.dart`: Defines the `PackageConfig` class and other types needed to use package configurations, and provides functions to find, read and From 38958749c9d2bc7403c9b67b54f90a981672bd32 Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 15:06:24 +0200 Subject: [PATCH 186/281] Fix dartdoc generation --- pkgs/package_config/lib/package_config_types.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index 482f82ac2..38b68ce6d 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -3,7 +3,13 @@ // BSD-style license that can be found in the LICENSE file. /// A package configuration is a way to assign file paths to package URIs, -/// and vice-versa, +/// and vice-versa. + +/// {@canonicalFor package_config.InvalidLanguageVersion} +/// {@canonicalFor package_config.LanguageVersion} +/// {@canonicalFor package_config.Package} +/// {@canonicalFor package_config.PackageConfig} +/// {@canonicalFor errors.PackageConfigError} library package_config.package_config_types; export 'src/package_config.dart' From 754c0a831f0db6d2c739e6abc3ab0cc6ccf06da4 Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 13 Sep 2021 16:16:00 +0200 Subject: [PATCH 187/281] Add /// --- pkgs/package_config/lib/package_config_types.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index 38b68ce6d..976009b6c 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -4,7 +4,7 @@ /// A package configuration is a way to assign file paths to package URIs, /// and vice-versa. - +/// /// {@canonicalFor package_config.InvalidLanguageVersion} /// {@canonicalFor package_config.LanguageVersion} /// {@canonicalFor package_config.Package} From 0674a0fcbd6126f03a28121e6c620155e978d014 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 11:00:11 +0100 Subject: [PATCH 188/281] Faster read; faster lookup; more tests; error on new package inside existing package root Previously adding (reading a file consisting of) n non-overlapping packages took O(n^2) time. Looking up a single package in a structure with n non-overlapping packages took O(n) time. Here this is changed so the timings are more like O(n) and O(1), respectively. (all of these should be taken with a grain of salt as not only the number of packages influence the time, but also the length of the paths which I completely ignore here). Run like this: ``` $ for i in 1 10 100 1000 5000 10000 50000; do dart test/bench.dart $i; done ``` (With no warmup, only run once etc --- there's lots of variations between runs, but for this purpose it doesn't really matter.) Before: Read file with 1 packages in 18 ms, looked up all packages in 0 ms Read file with 10 packages in 22 ms, looked up all packages in 0 ms Read file with 100 packages in 28 ms, looked up all packages in 1 ms Read file with 1000 packages in 78 ms, looked up all packages in 14 ms Read file with 5000 packages in 442 ms, looked up all packages in 384 ms Read file with 10000 packages in 2254 ms, looked up all packages in 1826 ms Read file with 50000 packages in 67572 ms, looked up all packages in 84050 ms After: Read file with 1 packages in 24 ms, looked up all packages in 0 ms Read file with 10 packages in 23 ms, looked up all packages in 0 ms Read file with 100 packages in 25 ms, looked up all packages in 1 ms Read file with 1000 packages in 60 ms, looked up all packages in 6 ms Read file with 5000 packages in 127 ms, looked up all packages in 10 ms Read file with 10000 packages in 187 ms, looked up all packages in 13 ms Read file with 50000 packages in 525 ms, looked up all packages in 61 ms Furthermore: * Previously no error was given if a package was inside the package root of another package. Now an error is given and tests are added. * Previously at least one test didn't work because of a json syntax error. This has been fixed. --- .../lib/src/package_config_impl.dart | 260 +++++++++--------- pkgs/package_config/test/bench.dart | 71 +++++ pkgs/package_config/test/parse_test.dart | 68 ++++- 3 files changed, 269 insertions(+), 130 deletions(-) create mode 100644 pkgs/package_config/test/bench.dart diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 4167d35f8..c22622b3a 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -54,12 +54,12 @@ class SimplePackageConfig implements PackageConfig { static PackageTree _validatePackages(Iterable originalPackages, List packages, void Function(Object error) onError) { var packageNames = {}; - var tree = MutablePackageTree(); + var tree = TrielikePackageTree(); for (var originalPackage in packages) { - SimplePackage? package; + SimplePackage? newPackage; if (originalPackage is! SimplePackage) { // SimplePackage validates these properties. - package = SimplePackage.validate( + newPackage = SimplePackage.validate( originalPackage.name, originalPackage.root, originalPackage.packageUriRoot, @@ -68,43 +68,58 @@ class SimplePackageConfig implements PackageConfig { originalPackage.relativeRoot, (error) { if (error is PackageConfigArgumentError) { onError(PackageConfigArgumentError(packages, 'packages', - 'Package ${package!.name}: ${error.message}')); + 'Package ${newPackage!.name}: ${error.message}')); } else { onError(error); } }); - if (package == null) continue; + if (newPackage == null) continue; } else { - package = originalPackage; + newPackage = originalPackage; } - var name = package.name; + var name = newPackage.name; if (packageNames.contains(name)) { onError(PackageConfigArgumentError( name, 'packages', "Duplicate package name '$name'")); continue; } packageNames.add(name); - tree.add(0, package, (error) { + tree.add(newPackage, (error) { if (error is ConflictException) { // There is a conflict with an existing package. var existingPackage = error.existingPackage; - if (error.isRootConflict) { - onError(PackageConfigArgumentError( - originalPackages, - 'packages', - 'Packages ${package!.name} and ${existingPackage.name} ' - 'have the same root directory: ${package.root}.\n')); - } else { - assert(error.isPackageRootConflict); - // Package is inside the package URI root of the existing package. - onError(PackageConfigArgumentError( - originalPackages, - 'packages', - 'Package ${package!.name} is inside the package URI root of ' - 'package ${existingPackage.name}.\n' - '${existingPackage.name} URI root: ' - '${existingPackage.packageUriRoot}\n' - '${package.name} root: ${package.root}\n')); + switch (error.conflictType) { + case ConflictType.SameRoots: + onError(PackageConfigArgumentError( + originalPackages, + 'packages', + 'Packages ${newPackage!.name} and ${existingPackage.name} ' + 'have the same root directory: ${newPackage.root}.\n')); + break; + case ConflictType.Interleaving: + // The new package is inside the package URI root of the existing + // package. + onError(PackageConfigArgumentError( + originalPackages, + 'packages', + 'Package ${newPackage!.name} is inside the root of ' + 'package ${existingPackage.name}, and the package root ' + 'of ${existingPackage.name} is inside the root of ' + '${newPackage.name}.\n' + '${existingPackage.name} package root: ' + '${existingPackage.packageUriRoot}\n' + '${newPackage.name} root: ${newPackage.root}\n')); + break; + case ConflictType.InsidePackageRoot: + onError(PackageConfigArgumentError( + originalPackages, + 'packages', + 'Package ${newPackage!.name} is inside the package root of ' + 'package ${existingPackage.name}.\n' + '${existingPackage.name} package root: ' + '${existingPackage.packageUriRoot}\n' + '${newPackage.name} root: ${newPackage.root}\n')); + break; } } else { // Any other error. @@ -367,6 +382,11 @@ abstract class PackageTree { SimplePackage? packageOf(Uri file); } +class _TrielikePackageTreeHelper { + SimplePackage? package; + Map map = {}; +} + /// Packages of a package configuration ordered by root path. /// /// A package has a root path and a package root path, where the latter @@ -375,122 +395,120 @@ abstract class PackageTree { /// A package is said to be inside another package if the root path URI of /// the latter is a prefix of the root path URI of the former. /// -/// No two packages of a package may have the same root path, so this -/// path prefix ordering defines a tree-like partial ordering on packages -/// of a configuration. -/// +/// No two packages of a package may have the same root path. /// The package root path of a package must not be inside another package's /// root path. -/// Entire other packages are allowed inside a package's root or -/// package root path. -/// -/// The package tree contains an ordered mapping of unrelated packages -/// (represented by their name) to their immediately nested packages' names. -class MutablePackageTree implements PackageTree { - /// A list of packages that are not nested inside each other. - final List packages = []; +/// Entire other packages are allowed inside a package's root. +class TrielikePackageTree implements PackageTree { + final Map _map = {}; - /// The tree of the immediately nested packages inside each package. - /// - /// Indexed by [Package.name]. - /// If a package has no nested packages (which is most often the case), - /// there is no tree object associated with it. - Map? _packageChildren; + /// A list of all packages. + final List _packages = []; @override Iterable get allPackages sync* { - for (var package in packages) { + for (var package in _packages) { yield package; } - var children = _packageChildren; - if (children != null) { - for (var tree in children.values) { - yield* tree.allPackages; + } + + bool _checkConflict(_TrielikePackageTreeHelper currentMapHelper, + SimplePackage newPackage, void Function(Object error) onError) { + if (currentMapHelper.package != null) { + var existingPackage = currentMapHelper.package!; + // Trying to add package that is inside the existing package. + // 1) If it's an exact match it's not allowed (i.e. the roots can't be + // the same). + if (newPackage.root.path.length == existingPackage.root.path.length) { + onError(ConflictException( + newPackage, existingPackage, ConflictType.SameRoots)); + return true; + } + // 2) The existing package has a packageUriRoot thats inside the + // root of the new package. + if (_beginsWith(0, newPackage.root.toString(), + existingPackage.packageUriRoot.toString())) { + onError(ConflictException( + newPackage, existingPackage, ConflictType.Interleaving)); + return true; + } + // 3) The new package is inside the packageUriRoot of existing package. + if (_beginsWith(0, existingPackage.packageUriRoot.toString(), + newPackage.root.toString())) { + onError(ConflictException( + newPackage, existingPackage, ConflictType.InsidePackageRoot)); + return true; } } + return false; } - /// Tries to (add) `package` to the tree. + /// Tries to add `newPackage` to the tree. /// /// Reports a [ConflictException] if the added package conflicts with an /// existing package. - /// It conflicts if its root or package root is the same as another - /// package's root or package root, or is between the two. + /// It conflicts if its root or package root is the same as an existing + /// package's root or package root, is between the two, or if it's inside the + /// package root of an existing package. /// - /// If a conflict is detected between [package] and a previous package, + /// If a conflict is detected between [newPackage] and a previous package, /// then [onError] is called with a [ConflictException] object - /// and the [package] is not added to the tree. + /// and the [newPackage] is not added to the tree. /// /// The packages are added in order of their root path. - /// It is never necessary to insert a node between two existing levels. - void add( - int start, SimplePackage package, void Function(Object error) onError) { - var path = package.root.toString(); - for (var treePackage in packages) { - // Check is package is inside treePackage. - var treePackagePath = treePackage.root.toString(); - assert(treePackagePath.length > start); - assert(path.startsWith(treePackagePath.substring(0, start))); - if (_beginsWith(start, treePackagePath, path)) { - // Package *is* inside treePackage. - var treePackagePathLength = treePackagePath.length; - if (path.length == treePackagePathLength) { - // Has same root. Do not add package. - onError(ConflictException.root(package, treePackage)); - return; - } - var treePackageUriRoot = treePackage.packageUriRoot.toString(); - if (_beginsWith(treePackagePathLength, path, treePackageUriRoot)) { - // The treePackage's package root is inside package, which is inside - // the treePackage. This is not allowed. - onError(ConflictException.packageRoot(package, treePackage)); - return; - } - _treeOf(treePackage).add(treePackagePathLength, package, onError); - return; + void add(SimplePackage newPackage, void Function(Object error) onError) { + var root = newPackage.root; + var currentMapHelper = _map[root.scheme] ??= _TrielikePackageTreeHelper(); + if (_checkConflict(currentMapHelper, newPackage, onError)) return; + var segments = root.pathSegments; + for (var i = 0; i < segments.length - 1; i++) { + var path = segments[i]; + currentMapHelper = + currentMapHelper.map[path] ??= _TrielikePackageTreeHelper(); + if (_checkConflict(currentMapHelper, newPackage, onError)) return; + } + currentMapHelper.package = newPackage; + _packages.add(newPackage); + } + + bool _isMatch(String path, _TrielikePackageTreeHelper currentMapHelper, + List potential) { + if (currentMapHelper.package != null) { + var currentPackage = currentMapHelper.package!; + var currentPackageRootLength = currentPackage.root.toString().length; + if (path.length == currentPackageRootLength) return true; + var currentPackageUriRoot = currentPackage.packageUriRoot.toString(); + // Is [file] is inside the package root of [currentPackage]? + if (currentPackageUriRoot.length == currentPackageRootLength || + _beginsWith(currentPackageRootLength, currentPackageUriRoot, path)) { + return true; } + potential.add(currentPackage); } - packages.add(package); + return false; } @override SimplePackage? packageOf(Uri file) { - return findPackageOf(0, file.toString()); - } - - /// Finds package containing [path] in this tree. - /// - /// Returns `null` if no such package is found. - /// - /// Assumes the first [start] characters of path agrees with all - /// the packages at this level of the tree. - SimplePackage? findPackageOf(int start, String path) { - for (var childPackage in packages) { - var childPath = childPackage.root.toString(); - if (_beginsWith(start, childPath, path)) { - // The [package] is inside [childPackage]. - var childPathLength = childPath.length; - if (path.length == childPathLength) return childPackage; - var uriRoot = childPackage.packageUriRoot.toString(); - // Is [package] is inside the URI root of [childPackage]. - if (uriRoot.length == childPathLength || - _beginsWith(childPathLength, uriRoot, path)) { - return childPackage; - } - return _packageChildren?[childPackage.name] - ?.findPackageOf(childPathLength, path) ?? - childPackage; + var currentMapHelper = _map[file.scheme]; + if (currentMapHelper == null) return null; + var path = file.toString(); + var potential = []; + if (_isMatch(path, currentMapHelper, potential)) { + return currentMapHelper.package; + } + var segments = file.pathSegments; + + for (var i = 0; i < segments.length - 1; i++) { + var segment = segments[i]; + currentMapHelper = currentMapHelper!.map[segment]; + if (currentMapHelper == null) break; + if (_isMatch(path, currentMapHelper, potential)) { + return currentMapHelper.package; } } - return null; - } - - /// Returns the [PackageTree] of the children of [package]. - /// - /// Ensures that the object is allocated if necessary. - MutablePackageTree _treeOf(SimplePackage package) { - var children = _packageChildren ??= {}; - return children[package.name] ??= MutablePackageTree(); + if (potential.isEmpty) return null; + return potential.last; } } @@ -516,6 +534,8 @@ bool _beginsWith(int start, String parentPath, String longerPath) { return true; } +enum ConflictType { SameRoots, Interleaving, InsidePackageRoot } + /// Conflict between packages added to the same configuration. /// /// The [package] conflicts with [existingPackage] if it has @@ -530,18 +550,10 @@ class ConflictException { final SimplePackage package; /// Whether the conflict is with the package URI root of [existingPackage]. - final bool isPackageRootConflict; + final ConflictType conflictType; /// Creates a root conflict between [package] and [existingPackage]. - ConflictException.root(this.package, this.existingPackage) - : isPackageRootConflict = false; - - /// Creates a package root conflict between [package] and [existingPackage]. - ConflictException.packageRoot(this.package, this.existingPackage) - : isPackageRootConflict = true; - - /// WHether the conflict is with the root URI of [existingPackage]. - bool get isRootConflict => !isPackageRootConflict; + ConflictException(this.package, this.existingPackage, this.conflictType); } /// Used for sorting packages by root path. diff --git a/pkgs/package_config/test/bench.dart b/pkgs/package_config/test/bench.dart new file mode 100644 index 000000000..746643185 --- /dev/null +++ b/pkgs/package_config/test/bench.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2021, 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. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:package_config/src/package_config_json.dart'; + +void throwError(Object error) => throw error; + +void bench(final int size, final bool doPrint) { + var sb = StringBuffer(); + sb.writeln('{'); + sb.writeln('"configVersion": 2,'); + sb.writeln('"packages": ['); + for (var i = 0; i < size; i++) { + if (i != 0) { + sb.writeln(','); + } + sb.writeln('{'); + sb.writeln(' "name": "p_$i",'); + sb.writeln(' "rootUri": "file:///p_$i/",'); + sb.writeln(' "packageUri": "lib/",'); + sb.writeln(' "languageVersion": "2.5",'); + sb.writeln(' "nonstandard": true'); + sb.writeln('}'); + } + sb.writeln('],'); + sb.writeln('"generator": "pub",'); + sb.writeln('"other": [42]'); + sb.writeln('}'); + var stopwatch = Stopwatch()..start(); + var config = parsePackageConfigBytes( + // ignore: unnecessary_cast + utf8.encode(sb.toString()) as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), + throwError); + final int read = stopwatch.elapsedMilliseconds; + + stopwatch.reset(); + for (var i = 0; i < size; i++) { + if (config.packageOf(Uri.parse('file:///p_$i/lib/src/foo.dart'))!.name != + 'p_$i') { + throw "Unexpected result!"; + } + } + final int lookup = stopwatch.elapsedMilliseconds; + + if (doPrint) { + print('Read file with $size packages in $read ms, ' + 'looked up all packages in $lookup ms'); + } +} + +void main(List args) { + if (args.length != 1 && args.length != 2) { + throw "Expects arguments: ?"; + } + final size = int.parse(args[0]); + if (args.length > 1) { + final warmups = int.parse(args[1]); + print("Performing $warmups warmup iterations."); + for (var i = 0; i < warmups; i++) { + bench(10, false); + } + } + + // Benchmark. + bench(size, true); +} diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index d5c2e7268..0a7770d58 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -272,6 +272,36 @@ void main() { Uri.parse('package:qux/diz')); }); + test('nested packages 2', () { + var configBytes = utf8.encode(json.encode({ + 'configVersion': 2, + 'packages': [ + {'name': 'foo', 'rootUri': '/', 'packageUri': 'lib/'}, + {'name': 'bar', 'rootUri': '/bar/', 'packageUri': 'lib/'}, + {'name': 'baz', 'rootUri': '/bar/baz/', 'packageUri': 'lib/'}, + {'name': 'qux', 'rootUri': '/qux/', 'packageUri': 'lib/'}, + ] + })); + // ignore: unnecessary_cast + var config = parsePackageConfigBytes(configBytes as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); + expect(config.version, 2); + expect( + config.packageOf(Uri.parse('file:///lala/lala.dart'))!.name, 'foo'); + expect(config.packageOf(Uri.parse('file:///bar/lala.dart'))!.name, 'bar'); + expect(config.packageOf(Uri.parse('file:///bar/baz/lala.dart'))!.name, + 'baz'); + expect(config.packageOf(Uri.parse('file:///qux/lala.dart'))!.name, 'qux'); + expect(config.toPackageUri(Uri.parse('file:///lib/diz')), + Uri.parse('package:foo/diz')); + expect(config.toPackageUri(Uri.parse('file:///bar/lib/diz')), + Uri.parse('package:bar/diz')); + expect(config.toPackageUri(Uri.parse('file:///bar/baz/lib/diz')), + Uri.parse('package:baz/diz')); + expect(config.toPackageUri(Uri.parse('file:///qux/lib/diz')), + Uri.parse('package:qux/diz')); + }); + group('invalid', () { void testThrows(String name, String source) { test(name, () { @@ -283,6 +313,21 @@ void main() { }); } + void testThrowsContains( + String name, String source, String containsString) { + test(name, () { + dynamic exception; + try { + parsePackageConfigBytes(utf8.encode(source) as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); + } catch (e) { + exception = e; + } + if (exception == null) fail("Didn't get exception"); + expect('$exception', contains(containsString)); + }); + } + testThrows('comment', '# comment\n {$cfg,$pkgs}'); testThrows('.packages file', 'foo:/foo\n'); testThrows('no configVersion', '{$pkgs}'); @@ -375,19 +420,30 @@ void main() { }); testThrows('duplicate package name', '{$cfg,"packages":[{$name,$root},{$name,"rootUri":"/other/"}]}'); - testThrows('same roots', - '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); - testThrows( + testThrowsContains( // The roots of foo and bar are the same. 'same roots', - '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}'); - testThrows( + '{$cfg,"packages":[{$name,$root},{"name":"bar",$root}]}', + 'the same root directory'); + testThrowsContains( + // The roots of foo and bar are the same. + 'same roots 2', + '{$cfg,"packages":[{$name,"rootUri":"/"},{"name":"bar","rootUri":"/"}]}', + 'the same root directory'); + testThrowsContains( // The root of bar is inside the root of foo, // but the package root of foo is inside the root of bar. 'between root and lib', '{$cfg,"packages":[' '{"name":"foo","rootUri":"/foo/","packageUri":"bar/lib/"},' - '{"name":"bar","rootUri":"/foo/bar/"},"packageUri":"baz/lib"]}'); + '{"name":"bar","rootUri":"/foo/bar/","packageUri":"baz/lib"}]}', + 'package root of foo is inside the root of bar'); + testThrowsContains( + 'root in lib', + '{$cfg,"packages":[' + '{"name":"foo","rootUri":"/foo/","packageUri":"lib/"},' + '{"name":"bar","rootUri":"/foo/lib/bar/","packageUri":"lib"}]}', + 'Package bar is inside the package root of package foo'); }); }); From c3b52af04b3a3e880c28fd988041341181c12cd1 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 11:07:49 +0100 Subject: [PATCH 189/281] Fix for 'Prefer using lowerCamelCase for constant names.' --- .../lib/src/package_config_impl.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index c22622b3a..90862e344 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -89,14 +89,14 @@ class SimplePackageConfig implements PackageConfig { // There is a conflict with an existing package. var existingPackage = error.existingPackage; switch (error.conflictType) { - case ConflictType.SameRoots: + case ConflictType.sameRoots: onError(PackageConfigArgumentError( originalPackages, 'packages', 'Packages ${newPackage!.name} and ${existingPackage.name} ' 'have the same root directory: ${newPackage.root}.\n')); break; - case ConflictType.Interleaving: + case ConflictType.interleaving: // The new package is inside the package URI root of the existing // package. onError(PackageConfigArgumentError( @@ -110,7 +110,7 @@ class SimplePackageConfig implements PackageConfig { '${existingPackage.packageUriRoot}\n' '${newPackage.name} root: ${newPackage.root}\n')); break; - case ConflictType.InsidePackageRoot: + case ConflictType.insidePackageRoot: onError(PackageConfigArgumentError( originalPackages, 'packages', @@ -421,7 +421,7 @@ class TrielikePackageTree implements PackageTree { // the same). if (newPackage.root.path.length == existingPackage.root.path.length) { onError(ConflictException( - newPackage, existingPackage, ConflictType.SameRoots)); + newPackage, existingPackage, ConflictType.sameRoots)); return true; } // 2) The existing package has a packageUriRoot thats inside the @@ -429,14 +429,14 @@ class TrielikePackageTree implements PackageTree { if (_beginsWith(0, newPackage.root.toString(), existingPackage.packageUriRoot.toString())) { onError(ConflictException( - newPackage, existingPackage, ConflictType.Interleaving)); + newPackage, existingPackage, ConflictType.interleaving)); return true; } // 3) The new package is inside the packageUriRoot of existing package. if (_beginsWith(0, existingPackage.packageUriRoot.toString(), newPackage.root.toString())) { onError(ConflictException( - newPackage, existingPackage, ConflictType.InsidePackageRoot)); + newPackage, existingPackage, ConflictType.insidePackageRoot)); return true; } } @@ -534,7 +534,7 @@ bool _beginsWith(int start, String parentPath, String longerPath) { return true; } -enum ConflictType { SameRoots, Interleaving, InsidePackageRoot } +enum ConflictType { sameRoots, interleaving, insidePackageRoot } /// Conflict between packages added to the same configuration. /// From a0159d4239e8c5728ba9ab3b1f3920082a376ecb Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 11:43:45 +0100 Subject: [PATCH 190/281] Allow inside lib anyway, for internal reasons --- .../lib/src/package_config_impl.dart | 4 ++++ pkgs/package_config/test/parse_test.dart | 21 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 90862e344..3ae54c2af 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -432,6 +432,9 @@ class TrielikePackageTree implements PackageTree { newPackage, existingPackage, ConflictType.interleaving)); return true; } + /* + For internal reasons we allow this (for now). One should still never do it + though. // 3) The new package is inside the packageUriRoot of existing package. if (_beginsWith(0, existingPackage.packageUriRoot.toString(), newPackage.root.toString())) { @@ -439,6 +442,7 @@ class TrielikePackageTree implements PackageTree { newPackage, existingPackage, ConflictType.insidePackageRoot)); return true; } + */ } return false; } diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 0a7770d58..174a099e0 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -438,12 +438,25 @@ void main() { '{"name":"foo","rootUri":"/foo/","packageUri":"bar/lib/"},' '{"name":"bar","rootUri":"/foo/bar/","packageUri":"baz/lib"}]}', 'package root of foo is inside the root of bar'); - testThrowsContains( - 'root in lib', - '{$cfg,"packages":[' + + // This shouldn't be allowed, but for internal reasons it is. + test("package inside package root", () { + var config = parsePackageConfigBytes( + utf8.encode( + '{$cfg,"packages":[' '{"name":"foo","rootUri":"/foo/","packageUri":"lib/"},' '{"name":"bar","rootUri":"/foo/lib/bar/","packageUri":"lib"}]}', - 'Package bar is inside the package root of package foo'); + ) as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), + throwError); + expect( + config + .packageOf(Uri.parse('file:///foo/lib/bar/lib/lala.dart'))! + .name, + 'foo'); // why not bar? + expect(config.toPackageUri(Uri.parse('file:///foo/lib/bar/lib/diz')), + Uri.parse('package:foo/bar/lib/diz')); // why not package:bar/diz? + }); }); }); From 4e5c229f81ec508fa2f8bbcb2ed7b520df05ac50 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 12:33:40 +0100 Subject: [PATCH 191/281] Feedback --- .../lib/src/package_config_impl.dart | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 3ae54c2af..86f31db8b 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -8,6 +8,8 @@ import 'util.dart'; export 'package_config.dart'; +const bool _disallowPackagesInsidePackageUriRoot = false; + // Implementations of the main data types exposed by the API of this package. class SimplePackageConfig implements PackageConfig { @@ -432,17 +434,18 @@ class TrielikePackageTree implements PackageTree { newPackage, existingPackage, ConflictType.interleaving)); return true; } - /* - For internal reasons we allow this (for now). One should still never do it - though. + + // For internal reasons we allow this (for now). One should still never do + // it thouh. // 3) The new package is inside the packageUriRoot of existing package. - if (_beginsWith(0, existingPackage.packageUriRoot.toString(), - newPackage.root.toString())) { - onError(ConflictException( - newPackage, existingPackage, ConflictType.insidePackageRoot)); - return true; + if (_disallowPackagesInsidePackageUriRoot) { + if (_beginsWith(0, existingPackage.packageUriRoot.toString(), + newPackage.root.toString())) { + onError(ConflictException( + newPackage, existingPackage, ConflictType.insidePackageRoot)); + return true; + } } - */ } return false; } From a731f2ec5454fbba1c3ebcd26eac76ad5edbf0b3 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 12:35:57 +0100 Subject: [PATCH 192/281] Feedback --- .../lib/src/package_config_impl.dart | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 86f31db8b..64bc50a8a 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -384,9 +384,9 @@ abstract class PackageTree { SimplePackage? packageOf(Uri file); } -class _TrielikePackageTreeHelper { +class _PackageTrieNode { SimplePackage? package; - Map map = {}; + Map map = {}; } /// Packages of a package configuration ordered by root path. @@ -402,7 +402,7 @@ class _TrielikePackageTreeHelper { /// root path. /// Entire other packages are allowed inside a package's root. class TrielikePackageTree implements PackageTree { - final Map _map = {}; + final Map _map = {}; /// A list of all packages. final List _packages = []; @@ -414,10 +414,10 @@ class TrielikePackageTree implements PackageTree { } } - bool _checkConflict(_TrielikePackageTreeHelper currentMapHelper, + bool _checkConflict(_PackageTrieNode currentTrieNode, SimplePackage newPackage, void Function(Object error) onError) { - if (currentMapHelper.package != null) { - var existingPackage = currentMapHelper.package!; + if (currentTrieNode.package != null) { + var existingPackage = currentTrieNode.package!; // Trying to add package that is inside the existing package. // 1) If it's an exact match it's not allowed (i.e. the roots can't be // the same). @@ -465,23 +465,23 @@ class TrielikePackageTree implements PackageTree { /// The packages are added in order of their root path. void add(SimplePackage newPackage, void Function(Object error) onError) { var root = newPackage.root; - var currentMapHelper = _map[root.scheme] ??= _TrielikePackageTreeHelper(); - if (_checkConflict(currentMapHelper, newPackage, onError)) return; + var currentTrieNode = _map[root.scheme] ??= _PackageTrieNode(); + if (_checkConflict(currentTrieNode, newPackage, onError)) return; var segments = root.pathSegments; for (var i = 0; i < segments.length - 1; i++) { var path = segments[i]; - currentMapHelper = - currentMapHelper.map[path] ??= _TrielikePackageTreeHelper(); - if (_checkConflict(currentMapHelper, newPackage, onError)) return; + currentTrieNode = + currentTrieNode.map[path] ??= _PackageTrieNode(); + if (_checkConflict(currentTrieNode, newPackage, onError)) return; } - currentMapHelper.package = newPackage; + currentTrieNode.package = newPackage; _packages.add(newPackage); } - bool _isMatch(String path, _TrielikePackageTreeHelper currentMapHelper, + bool _isMatch(String path, _PackageTrieNode currentTrieNode, List potential) { - if (currentMapHelper.package != null) { - var currentPackage = currentMapHelper.package!; + if (currentTrieNode.package != null) { + var currentPackage = currentTrieNode.package!; var currentPackageRootLength = currentPackage.root.toString().length; if (path.length == currentPackageRootLength) return true; var currentPackageUriRoot = currentPackage.packageUriRoot.toString(); @@ -497,21 +497,21 @@ class TrielikePackageTree implements PackageTree { @override SimplePackage? packageOf(Uri file) { - var currentMapHelper = _map[file.scheme]; - if (currentMapHelper == null) return null; + var currentTrieNode = _map[file.scheme]; + if (currentTrieNode == null) return null; var path = file.toString(); var potential = []; - if (_isMatch(path, currentMapHelper, potential)) { - return currentMapHelper.package; + if (_isMatch(path, currentTrieNode, potential)) { + return currentTrieNode.package; } var segments = file.pathSegments; for (var i = 0; i < segments.length - 1; i++) { var segment = segments[i]; - currentMapHelper = currentMapHelper!.map[segment]; - if (currentMapHelper == null) break; - if (_isMatch(path, currentMapHelper, potential)) { - return currentMapHelper.package; + currentTrieNode = currentTrieNode!.map[segment]; + if (currentTrieNode == null) break; + if (_isMatch(path, currentTrieNode, potential)) { + return currentTrieNode.package; } } if (potential.isEmpty) return null; From b280a3ed9a444102f14808592dcf040c286a1270 Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 12:37:42 +0100 Subject: [PATCH 193/281] Formatting --- pkgs/package_config/lib/src/package_config_impl.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 64bc50a8a..9966bb088 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -470,8 +470,7 @@ class TrielikePackageTree implements PackageTree { var segments = root.pathSegments; for (var i = 0; i < segments.length - 1; i++) { var path = segments[i]; - currentTrieNode = - currentTrieNode.map[path] ??= _PackageTrieNode(); + currentTrieNode = currentTrieNode.map[path] ??= _PackageTrieNode(); if (_checkConflict(currentTrieNode, newPackage, onError)) return; } currentTrieNode.package = newPackage; From fd7708b60bc8e8792cc1fb9af9f9408c75494bea Mon Sep 17 00:00:00 2001 From: Jens Johansen Date: Thu, 25 Nov 2021 15:11:35 +0100 Subject: [PATCH 194/281] feedback --- .../lib/src/package_config_impl.dart | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 9966bb088..aef817664 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -56,7 +56,7 @@ class SimplePackageConfig implements PackageConfig { static PackageTree _validatePackages(Iterable originalPackages, List packages, void Function(Object error) onError) { var packageNames = {}; - var tree = TrielikePackageTree(); + var tree = TriePackageTree(); for (var originalPackage in packages) { SimplePackage? newPackage; if (originalPackage is! SimplePackage) { @@ -386,6 +386,8 @@ abstract class PackageTree { class _PackageTrieNode { SimplePackage? package; + + /// Indexed by path segment. Map map = {}; } @@ -401,7 +403,8 @@ class _PackageTrieNode { /// The package root path of a package must not be inside another package's /// root path. /// Entire other packages are allowed inside a package's root. -class TrielikePackageTree implements PackageTree { +class TriePackageTree implements PackageTree { + /// Indexed by URI scheme. final Map _map = {}; /// A list of all packages. @@ -414,10 +417,10 @@ class TrielikePackageTree implements PackageTree { } } - bool _checkConflict(_PackageTrieNode currentTrieNode, - SimplePackage newPackage, void Function(Object error) onError) { - if (currentTrieNode.package != null) { - var existingPackage = currentTrieNode.package!; + bool _checkConflict(_PackageTrieNode node, SimplePackage newPackage, + void Function(Object error) onError) { + var existingPackage = node.package; + if (existingPackage != null) { // Trying to add package that is inside the existing package. // 1) If it's an exact match it's not allowed (i.e. the roots can't be // the same). @@ -465,26 +468,28 @@ class TrielikePackageTree implements PackageTree { /// The packages are added in order of their root path. void add(SimplePackage newPackage, void Function(Object error) onError) { var root = newPackage.root; - var currentTrieNode = _map[root.scheme] ??= _PackageTrieNode(); - if (_checkConflict(currentTrieNode, newPackage, onError)) return; + var node = _map[root.scheme] ??= _PackageTrieNode(); + if (_checkConflict(node, newPackage, onError)) return; var segments = root.pathSegments; + // Notice that we're skipping the last segment as it's always the empty + // string because roots are directories. for (var i = 0; i < segments.length - 1; i++) { var path = segments[i]; - currentTrieNode = currentTrieNode.map[path] ??= _PackageTrieNode(); - if (_checkConflict(currentTrieNode, newPackage, onError)) return; + node = node.map[path] ??= _PackageTrieNode(); + if (_checkConflict(node, newPackage, onError)) return; } - currentTrieNode.package = newPackage; + node.package = newPackage; _packages.add(newPackage); } - bool _isMatch(String path, _PackageTrieNode currentTrieNode, - List potential) { - if (currentTrieNode.package != null) { - var currentPackage = currentTrieNode.package!; + bool _isMatch( + String path, _PackageTrieNode node, List potential) { + var currentPackage = node.package; + if (currentPackage != null) { var currentPackageRootLength = currentPackage.root.toString().length; if (path.length == currentPackageRootLength) return true; var currentPackageUriRoot = currentPackage.packageUriRoot.toString(); - // Is [file] is inside the package root of [currentPackage]? + // Is [file] inside the package root of [currentPackage]? if (currentPackageUriRoot.length == currentPackageRootLength || _beginsWith(currentPackageRootLength, currentPackageUriRoot, path)) { return true; From 7095a039c0953341dc3176360091326913cba628 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 31 Jan 2022 10:26:28 -0800 Subject: [PATCH 195/281] Preemptively bump to a -dev version (dart-lang/package_config#118) The code in the repo has diverged from what was published in `2.0.2` so we don't want the pubspec to still have that version. There are no user facing changes. --- pkgs/package_config/CHANGELOG.md | 2 ++ pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index c85ac5011..8c58fbb63 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.0.3-dev + ## 2.0.2 - Update package description and README. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 6f80473c9..def12cbb7 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.2 +version: 2.0.3-dev description: Support for reading and writing Dart Package Configuration files. homepage: https://github.com/dart-lang/package_config From 66077cdbaa04489f86d4b14d2123519928f4db6e Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Mon, 7 Feb 2022 13:14:18 +0100 Subject: [PATCH 196/281] Fix broken link for language-versioning spec (dart-lang/package_config#120) Thanks! And yes, it's an issue that files do not have permalinks, but we also do want to use the hierarchical structure of the repo for placing them where they belong, and we don't want to keep copies around, because that risks older copies being stale. No good solution found. (If only you could tag files and refer to them by tag.) --- pkgs/package_config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 15ed4f6b2..712a23c80 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -2,7 +2,7 @@ [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) Support for working with **Package Configuration** files as described -in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). +in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/2.8/language-versioning/package-config-file-v2.md). A Dart package configuration file is used to resolve Dart package names (e.g. `foobar`) to Dart files containing the source code for that package (e.g. From fcea93be4967077f73dba731aa7f04728f0e2229 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:16:35 -0800 Subject: [PATCH 197/281] Bump actions/checkout from 2 to 3 (dart-lang/package_config#122) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 33bf62bd9..3db1d6c24 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From 2ee4e12f1a0d4cb90222587ca0f34b75cedcc794 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 29 Apr 2022 16:51:35 -0700 Subject: [PATCH 198/281] Update pubspec.yaml --- pkgs/pool/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 421baf5f2..feb49023d 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,10 +1,9 @@ name: pool version: 1.5.0 - description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. -homepage: https://github.com/dart-lang/pool +repository: https://github.com/dart-lang/pool environment: sdk: ">=2.12.0-0 <3.0.0" From 68d89c0e2c23bf9a7906c3a2de4c89153f1816b3 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 29 Apr 2022 23:52:59 +0000 Subject: [PATCH 199/281] rev to a dev version --- pkgs/pool/CHANGELOG.md | 2 ++ pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 9e0a5a519..c60ce08dc 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.5.1-dev + ## 1.5.0 * Stable release for null safety. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index feb49023d..5f50eb063 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.0 +version: 1.5.1-dev description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. From 0ed2b4a7b4929b18927ffdc6cd79a11349804333 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 30 Apr 2022 04:40:51 +0000 Subject: [PATCH 200/281] switch to package:lints --- pkgs/pool/CHANGELOG.md | 3 +++ pkgs/pool/analysis_options.yaml | 46 +-------------------------------- pkgs/pool/pubspec.yaml | 8 +++--- pkgs/pool/test/pool_test.dart | 1 - 4 files changed, 8 insertions(+), 50 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index c60ce08dc..c9694dd02 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,5 +1,8 @@ ## 1.5.1-dev +* Switch to using `package:lints` for analysis. +* Populate the pubspec `repository` field. + ## 1.5.0 * Stable release for null safety. diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index ae67bc00b..4fa4b8d13 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -1,49 +1,5 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: implicit-casts: false - -linter: - rules: - - avoid_function_literals_in_foreach_calls - - avoid_renaming_method_parameters - - avoid_returning_null - - avoid_returning_null_for_future - - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - - cancel_subscriptions - - comment_references - - constant_identifier_names - - control_flow_in_finally - - directives_ordering - - empty_statements - - hash_and_equals - - implementation_imports - - invariant_booleans - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - literal_only_boolean_expressions - - no_adjacent_strings_in_list - - non_constant_identifier_names - - only_throw_errors - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_const_constructors - - prefer_initializing_formals - - prefer_interpolation_to_compose_strings - - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - - test_types_in_equals - - throw_in_finally - - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_parenthesis - - unnecessary_statements diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 5f50eb063..26ca100b4 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -6,13 +6,13 @@ description: >- repository: https://github.com/dart-lang/pool environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: async: ^2.5.0 stack_trace: ^1.10.0 dev_dependencies: - fake_async: ^1.2.0-nullsafety - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + fake_async: ^1.2.0 + lints: ^1.0.0 + test: ^1.16.0 diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 20e92d597..2dd90f4a5 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'package:fake_async/fake_async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:pool/pool.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; From a690ba7b5b6a134eff6d1cd343c6e94c2fdc4dff Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 30 Apr 2022 05:22:12 +0000 Subject: [PATCH 201/281] test against Dart 2.15 --- pkgs/pool/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 9a455e756..76d5352da 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.15.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 From 87732e1abedb65a30fc357a5bace952a8f34e88c Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 2 May 2022 10:06:06 -0700 Subject: [PATCH 202/281] Update pubspec.yaml (dart-lang/package_config#123) --- pkgs/package_config/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index def12cbb7..d4ed6b94f 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,7 +1,7 @@ name: package_config version: 2.0.3-dev description: Support for reading and writing Dart Package Configuration files. -homepage: https://github.com/dart-lang/package_config +repository: https://github.com/dart-lang/package_config environment: sdk: '>=2.12.0 <3.0.0' From 43742539e3a04673f79fe68842a4285ce58eb8c1 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 19 May 2022 03:03:04 +0000 Subject: [PATCH 203/281] prep for publishing 2.0.3 --- pkgs/package_config/CHANGELOG.md | 6 +++++- pkgs/package_config/README.md | 1 + pkgs/package_config/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 8c58fbb63..4e095f2b0 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,4 +1,8 @@ -## 2.0.3-dev +## 2.0.3 + +- Improve file read performance; improve lookup performance. +- Emit an error when a package is inside the package root of another package. +- Fix a link in the readme. ## 2.0.2 diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 712a23c80..9e2e41f0b 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,5 +1,6 @@ [![Build Status](https://github.com/dart-lang/package_config/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/package_config/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) +[![package publisher](https://img.shields.io/pub/publisher/package_config.svg)](https://pub.dev/packages/package_config/publisher) Support for working with **Package Configuration** files as described in the Package Configuration v2 [design document](https://github.com/dart-lang/language/blob/master/accepted/2.8/language-versioning/package-config-file-v2.md). diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index d4ed6b94f..ea0f3b456 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.3-dev +version: 2.0.3 description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config From 20062b37f8a62b521bcbe1f4f2c300b25f4efcb1 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 20 May 2022 18:59:01 +0000 Subject: [PATCH 204/281] revert version change --- pkgs/package_config/CHANGELOG.md | 2 +- pkgs/package_config/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 4e095f2b0..9ecfe22b3 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.3 +## 2.0.3-dev - Improve file read performance; improve lookup performance. - Emit an error when a package is inside the package root of another package. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index ea0f3b456..d4ed6b94f 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.3 +version: 2.0.3-dev description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config From cd86f83cbd32bfe7221b3265b5516ea8e0b38756 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 23 May 2022 16:01:41 +0200 Subject: [PATCH 205/281] Adds `minVersion` to `findPackageConfig{,Uri}` methods. (dart-lang/package_config#125) * Adds `minVersion` to `findPackageConfig{,Uri}` methods. This parameter currently allows you to ignore `.packages` files while searching for a configuration file. If we later add a version 3 of the configuration, it should also allow ignoring version 2 configurations. --- pkgs/package_config/CHANGELOG.md | 9 +++- pkgs/package_config/lib/package_config.dart | 34 +++++++++++--- pkgs/package_config/lib/src/discovery.dart | 47 +++++++++++++------ .../lib/src/package_config.dart | 2 +- .../lib/src/package_config_impl.dart | 5 +- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/discovery_test.dart | 26 ++++++++++ .../test/discovery_uri_test.dart | 27 +++++++++++ 8 files changed, 127 insertions(+), 25 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 9ecfe22b3..b6e91bbd3 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,4 +1,11 @@ -## 2.0.3-dev +## 2.1.0 + +- Adds `minVersion` to `findPackageConfig` and `findPackageConfigVersion` + which allows ignoring earlier versions (which currently only means + ignoring version 1, aka. `.packages` files.) + +- Changes the version number of `SimplePackageConfig.empty` to the + current maximum version. - Improve file read performance; improve lookup performance. - Emit an error when a package is inside the package root of another package. diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index bd227e4e5..a2c0321b8 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -111,10 +111,21 @@ Future loadPackageConfigUri(Uri file, /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. /// +/// If [minVersion] is set to something greater than its default, +/// any lower-version configuration files are ignored in the search. +/// /// Returns `null` if no configuration file is found. Future findPackageConfig(Directory directory, - {bool recurse = true, void Function(Object error)? onError}) => - discover.findPackageConfig(directory, recurse, onError ?? throwError); + {bool recurse = true, + void Function(Object error)? onError, + int minVersion = 1}) { + if (minVersion > PackageConfig.maxVersion) { + throw ArgumentError.value(minVersion, 'minVersion', + 'Maximum known version is ${PackageConfig.maxVersion}'); + } + return discover.findPackageConfig( + directory, minVersion, recurse, onError ?? throwError); +} /// Finds a package configuration relative to [location]. /// @@ -155,13 +166,22 @@ Future findPackageConfig(Directory directory, /// a valid configuration from the invalid configuration file. /// If no [onError] is provided, errors are thrown immediately. /// +/// If [minVersion] is set to something greater than its default, +/// any lower-version configuration files are ignored in the search. +/// /// Returns `null` if no configuration file is found. Future findPackageConfigUri(Uri location, - {bool recurse = true, - Future Function(Uri uri)? loader, - void Function(Object error)? onError}) => - discover.findPackageConfigUri( - location, loader, onError ?? throwError, recurse); + {bool recurse = true, + int minVersion = 1, + Future Function(Uri uri)? loader, + void Function(Object error)? onError}) { + if (minVersion > PackageConfig.maxVersion) { + throw ArgumentError.value(minVersion, 'minVersion', + 'Maximum known version is ${PackageConfig.maxVersion}'); + } + return discover.findPackageConfigUri( + location, minVersion, loader, onError ?? throwError, recurse); +} /// Writes a package configuration to the provided directory. /// diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index a6cc451f2..ccc86ea23 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -25,15 +25,20 @@ final Uri parentPath = Uri(path: '..'); /// and stopping when something is found. /// /// * Check if a `.dart_tool/package_config.json` file exists in the directory. -/// * Check if a `.packages` file exists in the directory. +/// * Check if a `.packages` file exists in the directory +/// (if `minVersion <= 1`). /// * Repeat these checks for the parent directories until reaching the /// root directory if [recursive] is true. /// /// If any of these tests succeed, a `PackageConfig` class is returned. /// Returns `null` if no configuration was found. If a configuration /// is needed, then the caller can supply [PackageConfig.empty]. +/// +/// If [minVersion] is greated than 1, `.packages` files are ignored. +/// If [minVersion] is greater than the version read from the +/// `package_config.json` file, it too is ignored. Future findPackageConfig(Directory baseDirectory, - bool recursive, void Function(Object error) onError) async { + int minVersion, bool recursive, void Function(Object error) onError) async { var directory = baseDirectory; if (!directory.isAbsolute) directory = directory.absolute; if (!await directory.exists()) { @@ -41,7 +46,8 @@ Future findPackageConfig(Directory baseDirectory, } do { // Check for $cwd/.packages - var packageConfig = await findPackagConfigInDirectory(directory, onError); + var packageConfig = + await findPackagConfigInDirectory(directory, minVersion, onError); if (packageConfig != null) return packageConfig; if (!recursive) break; // Check in parent directories. @@ -55,6 +61,7 @@ Future findPackageConfig(Directory baseDirectory, /// Similar to [findPackageConfig] but based on a URI. Future findPackageConfigUri( Uri location, + int minVersion, Future Function(Uri uri)? loader, void Function(Object error) onError, bool recursive) async { @@ -67,6 +74,7 @@ Future findPackageConfigUri( if (location.isScheme('file')) { return findPackageConfig( Directory.fromUri(location.resolveUri(currentPath)), + minVersion, recursive, onError); } @@ -77,12 +85,15 @@ Future findPackageConfigUri( var file = location.resolveUri(packageConfigJsonPath); var bytes = await loader(file); if (bytes != null) { - return parsePackageConfigBytes(bytes, file, onError); + var config = parsePackageConfigBytes(bytes, file, onError); + if (config.version >= minVersion) return config; } - file = location.resolveUri(dotPackagesPath); - bytes = await loader(file); - if (bytes != null) { - return packages_file.parse(bytes, file, onError); + if (minVersion <= 1) { + file = location.resolveUri(dotPackagesPath); + bytes = await loader(file); + if (bytes != null) { + return packages_file.parse(bytes, file, onError); + } } if (!recursive) break; var parent = location.resolveUri(parentPath); @@ -102,15 +113,23 @@ Future findPackageConfigUri( /// If [onError] is supplied, parsing errors are reported using that, and /// a best-effort attempt is made to return a package configuration. /// This may be the empty package configuration. -Future findPackagConfigInDirectory( - Directory directory, void Function(Object error) onError) async { +/// +/// If [minVersion] is greated than 1, `.packages` files are ignored. +/// If [minVersion] is greater than the version read from the +/// `package_config.json` file, it too is ignored. +Future findPackagConfigInDirectory(Directory directory, + int minVersion, void Function(Object error) onError) async { var packageConfigFile = await checkForPackageConfigJsonFile(directory); if (packageConfigFile != null) { - return await readPackageConfigJsonFile(packageConfigFile, onError); + var config = await readPackageConfigJsonFile(packageConfigFile, onError); + if (config.version < minVersion) return null; + return config; } - packageConfigFile = await checkForDotPackagesFile(directory); - if (packageConfigFile != null) { - return await readDotPackagesFile(packageConfigFile, onError); + if (minVersion <= 1) { + packageConfigFile = await checkForDotPackagesFile(directory); + if (packageConfigFile != null) { + return await readDotPackagesFile(packageConfigFile, onError); + } } return null; } diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 3c5cc5196..ba52c147d 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -39,7 +39,7 @@ abstract class PackageConfig { /// including the two paths being the same. /// /// * No package's root must be the same as another package's root. - /// * The package-root of a package must be inside the pacakge's root. + /// * The package-root of a package must be inside the package's root. /// * If one package's package-root is inside another package's root, /// then the latter package's package root must not be inside the former /// package's root. (No getting between a package and its package root!) diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index aef817664..4c8f23443 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -37,8 +37,11 @@ class SimplePackageConfig implements PackageConfig { /// /// The empty configuration can be used in cases where no configuration is /// found, but code expects a non-null configuration. + /// + /// The version number is [PackageConfig.maxVersion] to avoid + /// minimum-version filters discarding the configuration. const SimplePackageConfig.empty() - : version = 1, + : version = PackageConfig.maxVersion, _packageTree = const EmptyPackageTree(), _packages = const {}, extraData = null; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index d4ed6b94f..56e30b5df 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.0.3-dev +version: 2.1.0 description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 4a1bba0a6..17b6aa099 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -201,6 +201,32 @@ void main() { expect(hadError, true); }); }); + + // Does not find .packages if no package_config.json and minVersion > 1. + fileTest('.packages ignored', { + '.packages': packagesFile, + 'script.dart': 'main(){}' + }, (Directory directory) async { + var config = (await findPackageConfig(directory, minVersion: 2)); + expect(config, null); + }); + + // Finds package_config.json in super-directory, with .packages in + // subdir and minVersion > 1. + fileTest('package_config.json recursive .packages ignored', { + '.dart_tool': { + 'package_config.json': packageConfigFile, + }, + 'subdir': { + '.packages': packagesFile, + 'script.dart': 'main(){}', + } + }, (Directory directory) async { + var config = (await findPackageConfig(subdir(directory, 'subdir/'), + minVersion: 2))!; + expect(config.version, 2); + validatePackagesFile(config, directory); + }); }); group('loadPackageConfig', () { diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index e487e471d..6183ce3ba 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -145,6 +145,33 @@ void main() { expect(() => findPackageConfigUri(directory, loader: loader), throwsA(TypeMatcher())); }); + + // Does not find .packages if no package_config.json and minVersion > 1. + loaderTest('.packages ignored', { + '.packages': packagesFile, + 'script.dart': 'main(){}' + }, (directory, loader) async { + var config = (await findPackageConfigUri(directory, + minVersion: 2, loader: loader)); + expect(config, null); + }); + + // Finds package_config.json in super-directory, with .packages in + // subdir and minVersion > 1. + loaderTest('package_config.json recursive ignores .packages', { + '.dart_tool': { + 'package_config.json': packageConfigFile, + }, + 'subdir': { + '.packages': packagesFile, + 'script.dart': 'main(){}', + } + }, (directory, loader) async { + var config = (await findPackageConfigUri(directory.resolve('subdir/'), + minVersion: 2, loader: loader))!; + expect(config.version, 2); + validatePackagesFile(config, directory); + }); }); group('loadPackageConfig', () { From 7dc5e0657a7402ef41433445fdbbe911845c709d Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 15 Jun 2022 13:04:13 -0700 Subject: [PATCH 206/281] prep for publishing 1.5.1 --- pkgs/pool/CHANGELOG.md | 2 +- pkgs/pool/README.md | 4 ++++ pkgs/pool/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index c9694dd02..64b51cc97 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.5.1-dev +## 1.5.1 * Switch to using `package:lints` for analysis. * Populate the pubspec `repository` field. diff --git a/pkgs/pool/README.md b/pkgs/pool/README.md index 641e77287..9e74f4d0d 100644 --- a/pkgs/pool/README.md +++ b/pkgs/pool/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/pool/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/pool/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) +[![package publisher](https://img.shields.io/pub/publisher/pool.svg)](https://pub.dev/packages/pool/publisher) + The pool package exposes a `Pool` class which makes it easy to manage a limited pool of resources. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 26ca100b4..b32438885 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.1-dev +version: 1.5.1 description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. From e05e41bff0698289b182a7adb2916cede315cdd0 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 15 Jun 2022 13:16:41 -0700 Subject: [PATCH 207/281] Update README.md --- pkgs/pool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/README.md b/pkgs/pool/README.md index 9e74f4d0d..b100ed35d 100644 --- a/pkgs/pool/README.md +++ b/pkgs/pool/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/pool/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/pool/actions/workflows/test-package.yml) +[![Dart CI](https://github.com/dart-lang/pool/actions/workflows/ci.yml/badge.svg)](https://github.com/dart-lang/pool/actions/workflows/ci.yml) [![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) [![package publisher](https://img.shields.io/pub/publisher/pool.svg)](https://pub.dev/packages/pool/publisher) From 279e48bdaa227646bb72e6fd982d50e217e59496 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 9 Nov 2022 15:47:54 -0800 Subject: [PATCH 208/281] blast_repo fixes (dart-lang/pool#58) Dependabot GitHub Action --- pkgs/pool/.github/dependabot.yml | 9 +++++++++ pkgs/pool/.github/workflows/ci.yml | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkgs/pool/.github/dependabot.yml diff --git a/pkgs/pool/.github/dependabot.yml b/pkgs/pool/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/pool/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 76d5352da..2a8bacf90 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.15.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 8c91bc23a9602502e8756dfd83bb2c25c3fb7baa Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 15 Nov 2022 12:29:53 -0800 Subject: [PATCH 209/281] blast_repo fixes (dart-lang/package_config#127) Dependabot GitHub Action --- pkgs/package_config/.github/dependabot.yml | 7 +++---- pkgs/package_config/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkgs/package_config/.github/dependabot.yml b/pkgs/package_config/.github/dependabot.yml index 430a85e7d..b2f1dec5a 100644 --- a/pkgs/package_config/.github/dependabot.yml +++ b/pkgs/package_config/.github/dependabot.yml @@ -4,8 +4,7 @@ version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" +- package-ecosystem: github-actions + directory: / schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" + interval: monthly diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 3db1d6c24..6b28e8555 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From ca63b528422112514abc5c124b9c436f4ccb7576 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 09:33:39 -0800 Subject: [PATCH 210/281] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/package_config#128) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 6b28e8555..9c89e08ce 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 02fdb7c3ae34ebf33d27a9040fee2bef90c83930 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:04:30 -0800 Subject: [PATCH 211/281] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/pool#59) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 2a8bacf90..90a25eba8 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.15.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 5266f39df95e54f623cd5bc10d068a6a67222c68 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 15:02:49 -0800 Subject: [PATCH 212/281] Migrate from no-implicit-casts to strict-casts (dart-lang/pool#60) --- pkgs/pool/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 4fa4b8d13..055ac1087 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -1,5 +1,5 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true From 681f007bdc748d94b1730624659d3d5725d3ec3b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 30 Jan 2023 09:23:49 -0800 Subject: [PATCH 213/281] Support latest pkg:build_web_compilers, lints. Update min SDK (dart-lang/package_config#129) --- pkgs/package_config/.github/workflows/test-package.yml | 2 +- pkgs/package_config/CHANGELOG.md | 4 ++++ pkgs/package_config/lib/src/package_config_impl.dart | 2 +- pkgs/package_config/lib/src/package_config_json.dart | 4 ++-- pkgs/package_config/lib/src/packages_file.dart | 2 +- pkgs/package_config/lib/src/util.dart | 4 ++-- pkgs/package_config/pubspec.yaml | 8 ++++---- pkgs/package_config/test/parse_test.dart | 2 +- 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 9c89e08ce..b28046588 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index b6e91bbd3..62ef87d6e 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.1-dev + +- Require Dart 2.18 + ## 2.1.0 - Adds `minVersion` to `findPackageConfig` and `findPackageConfigVersion` diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index 4c8f23443..f832d6adf 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -244,7 +244,7 @@ class SimplePackage implements Package { if (!root.hasScheme) { fatalError = true; } else if (!root.path.endsWith('/')) { - root = root.replace(path: root.path + '/'); + root = root.replace(path: '${root.path}/'); } } if (packageUriRoot == null) { diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index fe185a2ea..bd22db4ec 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -149,11 +149,11 @@ PackageConfig parsePackageConfigJson( var parsedRootUri = Uri.parse(rootUri!); var relativeRoot = !hasAbsolutePath(parsedRootUri); var root = baseLocation.resolveUri(parsedRootUri); - if (!root.path.endsWith('/')) root = root.replace(path: root.path + '/'); + if (!root.path.endsWith('/')) root = root.replace(path: '${root.path}/'); var packageRoot = root; if (packageUri != null) packageRoot = root.resolve(packageUri!); if (!packageRoot.path.endsWith('/')) { - packageRoot = packageRoot.replace(path: packageRoot.path + '/'); + packageRoot = packageRoot.replace(path: '${packageRoot.path}/'); } LanguageVersion? version; diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 244663326..3fd7db9b5 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -192,7 +192,7 @@ void write(StringSink output, PackageConfig config, uri = relativizeUri(uri, baseUri)!; } if (!uri.path.endsWith('/')) { - uri = uri.replace(path: uri.path + '/'); + uri = uri.replace(path: '${uri.path}/'); } output.write(uri); output.writeln(); diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 61488ac41..3bf1bece3 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -89,7 +89,7 @@ String checkValidPackageUri(Uri packageUri, String name) { } assert(badIndex < packageName.length); var badCharCode = packageName.codeUnitAt(badIndex); - var badChar = 'U+' + badCharCode.toRadixString(16).padLeft(4, '0'); + var badChar = 'U+${badCharCode.toRadixString(16).padLeft(4, '0')}'; if (badCharCode >= 0x20 && badCharCode <= 0x7e) { // Printable character. badChar = "'${packageName[badIndex]}' ($badChar)"; @@ -140,7 +140,7 @@ int firstNonWhitespaceChar(List bytes) { /// Appends a trailing `/` if the path doesn't end with one. String trailingSlash(String path) { if (path.isEmpty || path.endsWith('/')) return path; - return path + '/'; + return '$path/'; } /// Whether a URI should not be considered relative to the base URI. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 56e30b5df..08255ffa9 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,10 +1,10 @@ name: package_config -version: 2.1.0 +version: 2.1.1-dev description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.18.0 <3.0.0' dependencies: path: ^1.8.0 @@ -12,6 +12,6 @@ dependencies: dev_dependencies: build_runner: ^2.0.0 build_test: ^2.1.2 - build_web_compilers: ^3.0.0 - lints: ^1.0.0 + build_web_compilers: '>=3.0.0 <5.0.0' + lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 174a099e0..94269e20f 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -56,7 +56,7 @@ void main() { () => packages.parse(utf8.encode(content), baseFile, throwError), throwsA(TypeMatcher())); }); - test(name + ', handle error', () { + test('$name, handle error', () { var hadError = false; packages.parse(utf8.encode(content), baseFile, (error) { hadError = true; From b4f8e178edc247e271441c291efd9339f8b9eeb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 21:55:11 -0800 Subject: [PATCH 214/281] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/pool#63) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 90a25eba8..1bc0f7caa 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.15.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From d62677e559dded6170afaed6cda9d47e6871f7ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:35:01 -0800 Subject: [PATCH 215/281] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/pool#62) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 1bc0f7caa..b387db33f 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.15.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From f4e80817eb0b9ae444833887a510ca1c6eee39f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:37:33 -0800 Subject: [PATCH 216/281] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/package_config#131) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index b28046588..0123c53bb 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 6adef6143472173f725497c02cc895a44ad31041 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 12:42:17 -0800 Subject: [PATCH 217/281] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/package_config#130) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 0123c53bb..2fdd91f4e 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 923f2fd1abaae9f651dca5752469f7725ef474f2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 20 Feb 2023 09:30:38 -0800 Subject: [PATCH 218/281] blast_repo fixes (dart-lang/pool#64) auto-publish no-response --- pkgs/pool/.github/workflows/no-response.yml | 34 +++++++++++++++++++++ pkgs/pool/.github/workflows/publish.yaml | 14 +++++++++ 2 files changed, 48 insertions(+) create mode 100644 pkgs/pool/.github/workflows/no-response.yml create mode 100644 pkgs/pool/.github/workflows/publish.yaml diff --git a/pkgs/pool/.github/workflows/no-response.yml b/pkgs/pool/.github/workflows/no-response.yml new file mode 100644 index 000000000..ac3e456ec --- /dev/null +++ b/pkgs/pool/.github/workflows/no-response.yml @@ -0,0 +1,34 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/godofredoc/no-response for docs. + +name: No Response + +# Both `issue_comment` and `scheduled` event types are required. +on: + issue_comment: + types: [created] + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + +jobs: + noResponse: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + with: + responseRequiredLabel: "needs-info" + responseRequiredColor: 4774bc + daysUntilClose: 14 + # Comment to post when closing an Issue for lack of response. + closeComment: > + Without additional information we're not able to resolve this issue, + so it will be closed at this time. You're still free to add more + info and respond to any questions above, though. We'll reopen the + issue if you do. Thanks for your contribution! + token: ${{ github.token }} diff --git a/pkgs/pool/.github/workflows/publish.yaml b/pkgs/pool/.github/workflows/publish.yaml new file mode 100644 index 000000000..fcb7ccb89 --- /dev/null +++ b/pkgs/pool/.github/workflows/publish.yaml @@ -0,0 +1,14 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main From 1ef23dfd424b85581e0125ed216ea145acedfe6a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 20 Feb 2023 09:44:50 -0800 Subject: [PATCH 219/281] move to package:dart_flutter_team_lints, require Dart 2.19 (dart-lang/pool#65) --- pkgs/pool/.github/workflows/ci.yml | 2 +- pkgs/pool/CHANGELOG.md | 4 ++++ pkgs/pool/analysis_options.yaml | 2 +- pkgs/pool/pubspec.yaml | 6 +++--- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index b387db33f..31dd71900 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.15.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 64b51cc97..8d16309f1 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.2-dev + +* Require Dart 2.19 + ## 1.5.1 * Switch to using `package:lints` for analysis. diff --git a/pkgs/pool/analysis_options.yaml b/pkgs/pool/analysis_options.yaml index 055ac1087..44cda4da2 100644 --- a/pkgs/pool/analysis_options.yaml +++ b/pkgs/pool/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index b32438885..fff7adbef 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,18 +1,18 @@ name: pool -version: 1.5.1 +version: 1.5.2-dev description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. repository: https://github.com/dart-lang/pool environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.19.0 <3.0.0" dependencies: async: ^2.5.0 stack_trace: ^1.10.0 dev_dependencies: + dart_flutter_team_lints: ^0.1.0 fake_async: ^1.2.0 - lints: ^1.0.0 test: ^1.16.0 From fc983289b7f6e8db245ac82b7f5ecddf22cedf73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:52:56 -0700 Subject: [PATCH 220/281] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pool#67) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 31dd71900..0bf20516d 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 2b105c61b6234d7914c3bca865ac3cf07a6d7ca2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:35:25 -0700 Subject: [PATCH 221/281] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/pool#66) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 0bf20516d..5dbe7c0bf 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 1debd19e12803969fdb8c8b7b7e2580c8da21a1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:39:09 -0700 Subject: [PATCH 222/281] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/package_config#133) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 2fdd91f4e..8ca52ec84 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From df5710bafce012c8b492f8a4d554d77e4feb944f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:54:23 -0700 Subject: [PATCH 223/281] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/package_config#132) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 8ca52ec84..edf05e203 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From a543f2f29afe1a398ce53ddccc07ec4569838465 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:20:25 -0700 Subject: [PATCH 224/281] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/package_config#134) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index edf05e203..2c1be945f 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 982c8a82c64482fb2860a4314fdb3400cf4caffe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:30:07 -0700 Subject: [PATCH 225/281] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/pool#68) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 5dbe7c0bf..23400de05 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e6c23dc872370fff00dfe5c13433281ca6bfcbab Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 22 May 2023 09:20:32 -0700 Subject: [PATCH 226/281] blast_repo fixes (dart-lang/pool#69) dependabot --- pkgs/pool/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/pool/.github/dependabot.yml b/pkgs/pool/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/pool/.github/dependabot.yml +++ b/pkgs/pool/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 3af89623aacf60144f2449d0fe397d5b9ab95b05 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 22 May 2023 09:22:56 -0700 Subject: [PATCH 227/281] blast_repo fixes (dart-lang/package_config#135) dependabot --- pkgs/package_config/.github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/package_config/.github/dependabot.yml b/pkgs/package_config/.github/dependabot.yml index b2f1dec5a..c84404dc9 100644 --- a/pkgs/package_config/.github/dependabot.yml +++ b/pkgs/package_config/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: directory: / schedule: interval: monthly + labels: + - autosubmit From f2ffb25d3d862244389eed89c5082aa4aebd2c6e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 7 Jun 2023 17:22:34 -0700 Subject: [PATCH 228/281] Require Dart 3.0, update lints (dart-lang/pool#71) --- pkgs/pool/.github/workflows/ci.yml | 2 +- pkgs/pool/CHANGELOG.md | 5 ++--- pkgs/pool/pubspec.yaml | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 23400de05..9c507b69a 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 8d16309f1..e17e848cc 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,10 +1,9 @@ -## 1.5.2-dev +## 1.5.2-wip -* Require Dart 2.19 +* Require Dart 3.0. ## 1.5.1 -* Switch to using `package:lints` for analysis. * Populate the pubspec `repository` field. ## 1.5.0 diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index fff7adbef..08e4027a9 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,18 +1,18 @@ name: pool -version: 1.5.2-dev +version: 1.5.2-wip description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. repository: https://github.com/dart-lang/pool environment: - sdk: ">=2.19.0 <3.0.0" + sdk: ^3.0.0 dependencies: async: ^2.5.0 stack_trace: ^1.10.0 dev_dependencies: - dart_flutter_team_lints: ^0.1.0 + dart_flutter_team_lints: ^1.0.0 fake_async: ^1.2.0 test: ^1.16.0 From 812bd5b3aadf5d80e4b120b93237b9c250b5c9ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 02:16:18 +0000 Subject: [PATCH 229/281] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/pool#72) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 9c507b69a..c1107a5a7 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 52722601cb0bf2f90ba34b3e89f24c8f6028b746 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 20:23:57 +0000 Subject: [PATCH 230/281] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/package_config#138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 2c1be945f..34b8073d5 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 1b7fb96dbc5a3ff3f46f17eccd8872b16bcf2647 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 21 Jul 2023 10:37:29 -0700 Subject: [PATCH 231/281] Update to team lints, require Dart 3.0 (dart-lang/package_config#139) --- .../.github/workflows/test-package.yml | 2 +- pkgs/package_config/CHANGELOG.md | 4 ++-- pkgs/package_config/analysis_options.yaml | 2 +- pkgs/package_config/example/main.dart | 3 ++- pkgs/package_config/lib/package_config.dart | 2 +- .../lib/package_config_types.dart | 4 ++-- pkgs/package_config/lib/src/discovery.dart | 3 +-- pkgs/package_config/lib/src/errors.dart | 1 + .../lib/src/package_config_json.dart | 9 ++++++-- .../package_config/lib/src/packages_file.dart | 5 ++--- pkgs/package_config/pubspec.yaml | 8 +++---- pkgs/package_config/test/bench.dart | 22 +++++++++---------- pkgs/package_config/test/discovery_test.dart | 5 +++-- .../test/discovery_uri_test.dart | 6 ++--- pkgs/package_config/test/parse_test.dart | 20 ++++++++++------- pkgs/package_config/test/src/util_io.dart | 2 +- 16 files changed, 54 insertions(+), 44 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 34b8073d5..d14e9f416 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 62ef87d6e..d084d8514 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,6 +1,6 @@ -## 2.1.1-dev +## 2.1.1-wip -- Require Dart 2.18 +- Require Dart 3.0 ## 2.1.0 diff --git a/pkgs/package_config/analysis_options.yaml b/pkgs/package_config/analysis_options.yaml index 278ec4868..c0249e5e1 100644 --- a/pkgs/package_config/analysis_options.yaml +++ b/pkgs/package_config/analysis_options.yaml @@ -2,4 +2,4 @@ # 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. -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/pkgs/package_config/example/main.dart b/pkgs/package_config/example/main.dart index 42a596375..db137caf4 100644 --- a/pkgs/package_config/example/main.dart +++ b/pkgs/package_config/example/main.dart @@ -2,9 +2,10 @@ // 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. -import 'package:package_config/package_config.dart'; import 'dart:io' show Directory; +import 'package:package_config/package_config.dart'; + void main() async { var packageConfig = await findPackageConfig(Directory.current); if (packageConfig == null) { diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index a2c0321b8..8f40a8b65 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -9,7 +9,7 @@ /// configurations in the [specified format](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). library package_config.package_config; -import 'dart:io' show File, Directory; +import 'dart:io' show Directory, File; import 'dart:typed_data' show Uint8List; import 'src/discovery.dart' as discover; diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index 976009b6c..756be0518 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -12,6 +12,6 @@ /// {@canonicalFor errors.PackageConfigError} library package_config.package_config_types; -export 'src/package_config.dart' - show PackageConfig, Package, LanguageVersion, InvalidLanguageVersion; export 'src/errors.dart' show PackageConfigError; +export 'src/package_config.dart' + show InvalidLanguageVersion, LanguageVersion, Package, PackageConfig; diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index ccc86ea23..352bed8ca 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -5,10 +5,9 @@ import 'dart:io'; import 'dart:typed_data'; -import 'package_config_io.dart'; - import 'errors.dart'; import 'package_config_impl.dart'; +import 'package_config_io.dart'; import 'package_config_json.dart'; import 'packages_file.dart' as packages_file; import 'util_io.dart' show defaultLoader, pathJoin; diff --git a/pkgs/package_config/lib/src/errors.dart b/pkgs/package_config/lib/src/errors.dart index f3515711d..69c41370a 100644 --- a/pkgs/package_config/lib/src/errors.dart +++ b/pkgs/package_config/lib/src/errors.dart @@ -29,4 +29,5 @@ class PackageConfigFormatException extends FormatException } /// The default `onError` handler. +// ignore: only_throw_errors Never throwError(Object error) => throw error; diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index bd22db4ec..47e7e96b6 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -167,7 +167,9 @@ PackageConfig parsePackageConfigJson( name!, root, packageRoot, version, extraData, relativeRoot, (error) { if (error is ArgumentError) { onError( - PackageConfigFormatException(error.message, error.invalidValue)); + PackageConfigFormatException( + error.message.toString(), error.invalidValue), + ); } else { onError(error); } @@ -214,7 +216,10 @@ PackageConfig parsePackageConfigJson( } return SimplePackageConfig(configVersion!, packageList!, extraData, (error) { if (error is ArgumentError) { - onError(PackageConfigFormatException(error.message, error.invalidValue)); + onError( + PackageConfigFormatException( + error.message.toString(), error.invalidValue), + ); } else { onError(error); } diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 3fd7db9b5..5d1467755 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -2,10 +2,9 @@ // 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. +import 'errors.dart'; import 'package_config_impl.dart'; - import 'util.dart'; -import 'errors.dart'; /// The language version prior to the release of language versioning. /// @@ -127,7 +126,7 @@ PackageConfig parse( var package = SimplePackage.validate(packageName, rootUri, packageLocation, _languageVersion, null, relativeRoot, (error) { if (error is ArgumentError) { - onError(PackageConfigFormatException(error.message, source)); + onError(PackageConfigFormatException(error.message.toString(), source)); } else { onError(error); } diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 08255ffa9..e121ab033 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,10 +1,10 @@ name: package_config -version: 2.1.1-dev +version: 2.1.1-wip description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config environment: - sdk: '>=2.18.0 <3.0.0' + sdk: ^3.0.0 dependencies: path: ^1.8.0 @@ -12,6 +12,6 @@ dependencies: dev_dependencies: build_runner: ^2.0.0 build_test: ^2.1.2 - build_web_compilers: '>=3.0.0 <5.0.0' - lints: ^2.0.0 + build_web_compilers: ^4.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/bench.dart b/pkgs/package_config/test/bench.dart index 746643185..8428481f7 100644 --- a/pkgs/package_config/test/bench.dart +++ b/pkgs/package_config/test/bench.dart @@ -5,10 +5,9 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:package_config/src/errors.dart'; import 'package:package_config/src/package_config_json.dart'; -void throwError(Object error) => throw error; - void bench(final int size, final bool doPrint) { var sb = StringBuffer(); sb.writeln('{'); @@ -32,20 +31,21 @@ void bench(final int size, final bool doPrint) { sb.writeln('}'); var stopwatch = Stopwatch()..start(); var config = parsePackageConfigBytes( - // ignore: unnecessary_cast - utf8.encode(sb.toString()) as Uint8List, - Uri.parse('file:///tmp/.dart_tool/file.dart'), - throwError); - final int read = stopwatch.elapsedMilliseconds; + // ignore: unnecessary_cast + utf8.encode(sb.toString()) as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), + throwError, + ); + final read = stopwatch.elapsedMilliseconds; stopwatch.reset(); for (var i = 0; i < size; i++) { if (config.packageOf(Uri.parse('file:///p_$i/lib/src/foo.dart'))!.name != 'p_$i') { - throw "Unexpected result!"; + throw StateError('Unexpected result!'); } } - final int lookup = stopwatch.elapsedMilliseconds; + final lookup = stopwatch.elapsedMilliseconds; if (doPrint) { print('Read file with $size packages in $read ms, ' @@ -55,12 +55,12 @@ void bench(final int size, final bool doPrint) { void main(List args) { if (args.length != 1 && args.length != 2) { - throw "Expects arguments: ?"; + throw ArgumentError('Expects arguments: ?'); } final size = int.parse(args[0]); if (args.length > 1) { final warmups = int.parse(args[1]); - print("Performing $warmups warmup iterations."); + print('Performing $warmups warmup iterations.'); for (var i = 0; i < warmups; i++) { bench(10, false); } diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 17b6aa099..3eb0ea153 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -6,8 +6,9 @@ library package_config.discovery_test; import 'dart:io'; -import 'package:test/test.dart'; + import 'package:package_config/package_config.dart'; +import 'package:test/test.dart'; import 'src/util.dart'; import 'src/util_io.dart'; @@ -207,7 +208,7 @@ void main() { '.packages': packagesFile, 'script.dart': 'main(){}' }, (Directory directory) async { - var config = (await findPackageConfig(directory, minVersion: 2)); + var config = await findPackageConfig(directory, minVersion: 2); expect(config, null); }); diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index 6183ce3ba..c8fbcb87c 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -5,8 +5,8 @@ @TestOn('vm') library package_config.discovery_test; -import 'package:test/test.dart'; import 'package:package_config/package_config.dart'; +import 'package:test/test.dart'; import 'src/util.dart'; @@ -151,8 +151,8 @@ void main() { '.packages': packagesFile, 'script.dart': 'main(){}' }, (directory, loader) async { - var config = (await findPackageConfigUri(directory, - minVersion: 2, loader: loader)); + var config = + await findPackageConfigUri(directory, minVersion: 2, loader: loader); expect(config, null); }); diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 94269e20f..ad4c74949 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -5,14 +5,13 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:test/test.dart'; - import 'package:package_config/package_config_types.dart'; -import 'package:package_config/src/packages_file.dart' as packages; +import 'package:package_config/src/errors.dart'; import 'package:package_config/src/package_config_json.dart'; -import 'src/util.dart'; +import 'package:package_config/src/packages_file.dart' as packages; +import 'package:test/test.dart'; -void throwError(Object error) => throw error; +import 'src/util.dart'; void main() { group('.packages', () { @@ -318,8 +317,12 @@ void main() { test(name, () { dynamic exception; try { - parsePackageConfigBytes(utf8.encode(source) as Uint8List, - Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError); + parsePackageConfigBytes( + // ignore: unnecessary_cast + utf8.encode(source) as Uint8List, + Uri.parse('file:///tmp/.dart_tool/file.dart'), + throwError, + ); } catch (e) { exception = e; } @@ -440,8 +443,9 @@ void main() { 'package root of foo is inside the root of bar'); // This shouldn't be allowed, but for internal reasons it is. - test("package inside package root", () { + test('package inside package root', () { var config = parsePackageConfigBytes( + // ignore: unnecessary_cast utf8.encode( '{$cfg,"packages":[' '{"name":"foo","rootUri":"/foo/","packageUri":"lib/"},' diff --git a/pkgs/package_config/test/src/util_io.dart b/pkgs/package_config/test/src/util_io.dart index 109dff112..e032556f4 100644 --- a/pkgs/package_config/test/src/util_io.dart +++ b/pkgs/package_config/test/src/util_io.dart @@ -4,8 +4,8 @@ import 'dart:io'; -import 'package:test/test.dart'; import 'package:package_config/src/util_io.dart'; +import 'package:test/test.dart'; /// Creates a directory structure from [description] and runs [fileTest]. /// From 687ba74f82da9ca33282e2f9b2f5d5e2fecc0d7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 02:18:57 +0000 Subject: [PATCH 232/281] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/pool#73) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index c1107a5a7..6c8907b19 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 9c69749f299fb5f031f6a8a281b4b2799feb8303 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 20:17:04 +0000 Subject: [PATCH 233/281] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/package_config#140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index d14e9f416..5ee9b9226 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 9a4199c431608c955f2175b180d6ae6e1292b6ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 02:44:48 +0000 Subject: [PATCH 234/281] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/pool#75) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 6c8907b19..eb8c73d8d 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 4225920dc204d378248efa525b1cefcbe6988ca3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:24:54 +0000 Subject: [PATCH 235/281] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/package_config#142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 5ee9b9226..6a09c5a68 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From a8ce33657f705a401c8a5322bce18e7f617e44f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:26:42 +0000 Subject: [PATCH 236/281] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/package_config#141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 6a09c5a68..c3e89aacd 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 7265fe753784a2cd8a49db7ab1303b35889cc42c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:15:10 -0700 Subject: [PATCH 237/281] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/pool#74) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index eb8c73d8d..d945ee6f5 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 3e4052b205191fb722743a45be1b3f19bf2f4fb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 02:05:22 +0000 Subject: [PATCH 238/281] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/pool#76) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/pool#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/pool#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index d945ee6f5..28e9efa21 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 41c1ecc06252bafd30b8875eb399c36ae97a2117 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:54:44 +0000 Subject: [PATCH 239/281] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/pool#77) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 28e9efa21..b69f2bd51 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From aff00e80119d63faa70d6ba7bb7caa230f1003be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 20:33:04 +0000 Subject: [PATCH 240/281] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/package_config#143) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index c3e89aacd..dd76bff17 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 2019cfabc7ee175b6b9c204a2c98e1e728de926e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 21:39:05 +0000 Subject: [PATCH 241/281] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/package_config#144) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index dd76bff17..2aa74dfe3 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From b6943f4bd6bf20178569486fd885afc63575d62d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Dec 2023 09:57:23 -0800 Subject: [PATCH 242/281] blast_repo fixes (dart-lang/pool#78) no-response --- pkgs/pool/.github/workflows/no-response.yml | 35 +++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/pkgs/pool/.github/workflows/no-response.yml b/pkgs/pool/.github/workflows/no-response.yml index ac3e456ec..8e5ed57cd 100644 --- a/pkgs/pool/.github/workflows/no-response.yml +++ b/pkgs/pool/.github/workflows/no-response.yml @@ -1,12 +1,10 @@ # A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/godofredoc/no-response for docs. +# more information; see https://github.com/actions/stale. name: No Response -# Both `issue_comment` and `scheduled` event types are required. +# Run as a daily cron. on: - issue_comment: - types: [created] schedule: # Every day at 8am - cron: '0 8 * * *' @@ -14,21 +12,26 @@ on: # All permissions not specified are set to 'none'. permissions: issues: write + pull-requests: write jobs: - noResponse: + no-response: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 with: - responseRequiredLabel: "needs-info" - responseRequiredColor: 4774bc - daysUntilClose: 14 - # Comment to post when closing an Issue for lack of response. - closeComment: > - Without additional information we're not able to resolve this issue, - so it will be closed at this time. You're still free to add more - info and respond to any questions above, though. We'll reopen the - issue if you do. Thanks for your contribution! - token: ${{ github.token }} + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! From c6932a4a2b09760b71de189fbe59b8cd93883d94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 02:33:22 +0000 Subject: [PATCH 243/281] Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/pool#79) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0.
Release notes

Sourced from actions/stale's releases.

v9.0.0

Breaking Changes

  1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
  2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

What Else Changed

  1. Performance optimization that removes unnecessary API calls by @​dsame dart-lang/pool#1033 fixes dart-lang/pool#792
  2. Logs displaying current github API rate limit by @​dsame dart-lang/pool#1032 addresses dart-lang/pool#1029

For more information, please read the action documentation and its section about statefulness

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v8...v9.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=8.0.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pool/.github/workflows/no-response.yml b/pkgs/pool/.github/workflows/no-response.yml index 8e5ed57cd..ab1ac4984 100644 --- a/pkgs/pool/.github/workflows/no-response.yml +++ b/pkgs/pool/.github/workflows/no-response.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e with: # Don't automatically mark inactive issues+PRs as stale. days-before-stale: -1 From a9396b06c4c4a2a32072962293ae4345d79201bf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 10 Jan 2024 13:21:18 -0800 Subject: [PATCH 244/281] Update to latest lints, Require Dart 3.2 (dart-lang/package_config#145) --- .../.github/workflows/test-package.yml | 2 +- pkgs/package_config/CHANGELOG.md | 2 +- pkgs/package_config/lib/package_config.dart | 4 ++-- pkgs/package_config/lib/src/errors.dart | 9 ++++---- .../lib/src/package_config.dart | 8 +++---- .../lib/src/package_config_impl.dart | 13 +++-------- .../lib/src/package_config_io.dart | 2 +- .../lib/src/package_config_json.dart | 8 +++---- .../package_config/lib/src/packages_file.dart | 6 ----- pkgs/package_config/pubspec.yaml | 4 ++-- pkgs/package_config/test/discovery_test.dart | 22 ++++++++----------- .../test/discovery_uri_test.dart | 14 ++++++------ .../test/package_config_impl_test.dart | 2 +- pkgs/package_config/test/parse_test.dart | 4 ++-- pkgs/package_config/test/src/util.dart | 2 +- 15 files changed, 42 insertions(+), 60 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 2aa74dfe3..2e475912a 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.2, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index d084d8514..a682bc3a4 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.1.1-wip -- Require Dart 3.0 +- Require Dart 3.2 ## 2.1.0 diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 8f40a8b65..194fe894e 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -102,7 +102,7 @@ Future loadPackageConfigUri(Uri file, /// then the parent directories are checked recursively, /// all the way to the root directory, to check if those contains /// a package configuration. -/// If [recurse] is set to [false], this parent directory check is not +/// If [recurse] is set to `false`, this parent directory check is not /// performed. /// /// If [onError] is provided, the configuration file parsing will report errors @@ -140,7 +140,7 @@ Future findPackageConfig(Directory directory, /// then the parent directories are checked recursively, /// all the way to the root directory, to check if those contains /// a package configuration. -/// If [recurse] is set to [false], this parent directory check is not +/// If [recurse] is set to `false`, this parent directory check is not /// performed. /// /// If [loader] is provided, URIs are loaded using that function. diff --git a/pkgs/package_config/lib/src/errors.dart b/pkgs/package_config/lib/src/errors.dart index 69c41370a..a66fef7f3 100644 --- a/pkgs/package_config/lib/src/errors.dart +++ b/pkgs/package_config/lib/src/errors.dart @@ -12,8 +12,9 @@ abstract class PackageConfigError { class PackageConfigArgumentError extends ArgumentError implements PackageConfigError { - PackageConfigArgumentError(Object? value, String name, String message) - : super.value(value, name, message); + PackageConfigArgumentError( + Object? super.value, String super.name, String super.message) + : super.value(); PackageConfigArgumentError.from(ArgumentError error) : super.value(error.invalidValue, error.name, error.message); @@ -21,8 +22,8 @@ class PackageConfigArgumentError extends ArgumentError class PackageConfigFormatException extends FormatException implements PackageConfigError { - PackageConfigFormatException(String message, Object? source, [int? offset]) - : super(message, source, offset); + PackageConfigFormatException(super.message, Object? super.source, + [super.offset]); PackageConfigFormatException.from(FormatException exception) : super(exception.message, exception.source, exception.offset); diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index ba52c147d..c00ac67af 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -32,7 +32,7 @@ abstract class PackageConfig { /// absolute directory URIs, valid language version, if any), /// and there must not be two packages with the same name. /// - /// The package's root ([Package.rootUri]) and package-root + /// The package's root ([Package.root]) and package-root /// ([Package.packageUriRoot]) paths must satisfy a number of constraints /// We say that one path (which we know ends with a `/` charater) /// is inside another path, if the latter path is a prefix of the former path, @@ -95,7 +95,7 @@ abstract class PackageConfig { /// Parses the JSON data of a package configuration file. /// - /// The [configuration] must be a JSON-like Dart data structure, + /// The [jsonData] must be a JSON-like Dart data structure, /// like the one provided by parsing JSON text using `dart:convert`, /// containing a valid package configuration. /// @@ -167,7 +167,7 @@ abstract class PackageConfig { /// Provides the associated package for a specific [file] (or directory). /// /// Returns a [Package] which contains the [file]'s path, if any. - /// That is, the [Package.rootUri] directory is a parent directory + /// That is, the [Package.root] directory is a parent directory /// of the [file]'s location. /// /// Returns `null` if the file does not belong to any package. @@ -247,7 +247,7 @@ abstract class Package { /// Is always an absolute URI with no query or fragment parts, /// and with a path ending in `/`. /// - /// All files in the [rootUri] directory are considered + /// All files in the [root] directory are considered /// part of the package for purposes where that that matters. Uri get root; diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index f832d6adf..d8e8d495f 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -141,12 +141,6 @@ class SimplePackageConfig implements PackageConfig { @override Package? operator [](String packageName) => _packages[packageName]; - /// Provides the associated package for a specific [file] (or directory). - /// - /// Returns a [Package] which contains the [file]'s path. - /// That is, the [Package.rootUri] directory is a parent directory - /// of the [file]'s location. - /// Returns `null` if the file does not belong to any package. @override Package? packageOf(Uri file) => _packageTree.packageOf(file); @@ -270,7 +264,7 @@ class SimplePackage implements Package { } } -/// Checks whether [version] is a valid Dart language version string. +/// Checks whether [source] is a valid Dart language version string. /// /// The format is (as RegExp) `^(0|[1-9]\d+)\.(0|[1-9]\d+)$`. /// @@ -553,9 +547,8 @@ enum ConflictType { sameRoots, interleaving, insidePackageRoot } /// Conflict between packages added to the same configuration. /// /// The [package] conflicts with [existingPackage] if it has -/// the same root path ([isRootConflict]) or the package URI root path -/// of [existingPackage] is inside the root path of [package] -/// ([isPackageRootConflict]). +/// the same root path or the package URI root path +/// of [existingPackage] is inside the root path of [package]. class ConflictException { /// The existing package that [package] conflicts with. final SimplePackage existingPackage; diff --git a/pkgs/package_config/lib/src/package_config_io.dart b/pkgs/package_config/lib/src/package_config_io.dart index 9aed621e0..8c5773b2b 100644 --- a/pkgs/package_config/lib/src/package_config_io.dart +++ b/pkgs/package_config/lib/src/package_config_io.dart @@ -38,7 +38,7 @@ const packagesFileName = '.packages'; /// If the [file] is a `.packages` file and [preferNewest] is true, /// first checks whether there is an adjacent `.dart_tool/package_config.json` /// file, and if so, reads that instead. -/// If [preferNewset] is false, the specified file is loaded even if it is +/// If [preferNewest] is false, the specified file is loaded even if it is /// a `.packages` file and there is an available `package_config.json` file. /// /// The file must exist and be a normal file. diff --git a/pkgs/package_config/lib/src/package_config_json.dart b/pkgs/package_config/lib/src/package_config_json.dart index 47e7e96b6..65560a0f0 100644 --- a/pkgs/package_config/lib/src/package_config_json.dart +++ b/pkgs/package_config/lib/src/package_config_json.dart @@ -75,10 +75,8 @@ PackageConfig parsePackageConfigString( /// where the integer numeral cannot have a sign, and can only have a /// leading zero if the entire numeral is a single zero. /// -/// All other properties are stored in [extraData]. -/// /// The [baseLocation] is used as base URI to resolve the "rootUri" -/// URI referencestring. +/// URI reference string. PackageConfig parsePackageConfigJson( Object? json, Uri baseLocation, void Function(Object error) onError) { if (!baseLocation.hasScheme || baseLocation.isScheme('package')) { @@ -93,7 +91,7 @@ PackageConfig parsePackageConfigJson( String typeName() { if (0 is T) return 'int'; if ('' is T) return 'string'; - if (const [] is T) return 'array'; + if (const [] is T) return 'array'; return 'object'; } @@ -239,7 +237,7 @@ void writePackageConfigJsonString( PackageConfig config, Uri? baseUri, StringSink output) { // Can be optimized. var data = packageConfigToJson(config, baseUri); - output.write(JsonEncoder.withIndent(' ').convert(data)); + output.write(const JsonEncoder.withIndent(' ').convert(data)); } Map packageConfigToJson(PackageConfig config, Uri? baseUri) => diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index 5d1467755..f84db1075 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -148,12 +148,6 @@ PackageConfig parse( /// /// If [baseUri] is provided, package locations will be made relative /// to the base URI, if possible, before writing. -/// -/// If [allowDefaultPackage] is `true`, the [packageMapping] may contain an -/// empty string mapping to the _default package name_. -/// -/// All the keys of [packageMapping] must be valid package names, -/// and the values must be URIs that do not have the `package:` scheme. void write(StringSink output, PackageConfig config, {Uri? baseUri, String? comment}) { if (baseUri != null && !baseUri.isAbsolute) { diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index e121ab033..b7130793f 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -4,7 +4,7 @@ description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config environment: - sdk: ^3.0.0 + sdk: ^3.2.0 dependencies: path: ^1.8.0 @@ -13,5 +13,5 @@ dev_dependencies: build_runner: ^2.0.0 build_test: ^2.1.2 build_web_compilers: ^4.0.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 3eb0ea153..ee77559b1 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -59,7 +59,7 @@ void main() { fileTest('package_config.json', { '.packages': 'invalid .packages file', 'script.dart': 'main(){}', - 'packages': {'shouldNotBeFound': {}}, + 'packages': {'shouldNotBeFound': {}}, '.dart_tool': { 'package_config.json': packageConfigFile, } @@ -73,7 +73,7 @@ void main() { fileTest('.packages', { '.packages': packagesFile, 'script.dart': 'main(){}', - 'packages': {'shouldNotBeFound': {}} + 'packages': {'shouldNotBeFound': {}} }, (Directory directory) async { var config = (await findPackageConfig(directory))!; expect(config.version, 1); // Found .packages file. @@ -108,7 +108,7 @@ void main() { // Does not find a packages/ directory, and returns null if nothing found. fileTest('package directory packages not supported', { 'packages': { - 'foo': {}, + 'foo': {}, } }, (Directory directory) async { var config = await findPackageConfig(directory); @@ -119,15 +119,13 @@ void main() { fileTest('invalid .packages', { '.packages': 'not a .packages file', }, (Directory directory) { - expect(findPackageConfig(directory), - throwsA(TypeMatcher())); + expect(findPackageConfig(directory), throwsA(isA())); }); fileTest('invalid .packages as JSON', { '.packages': packageConfigFile, }, (Directory directory) { - expect(findPackageConfig(directory), - throwsA(TypeMatcher())); + expect(findPackageConfig(directory), throwsA(isA())); }); fileTest('invalid .packages', { @@ -135,8 +133,7 @@ void main() { 'package_config.json': 'not a JSON file', } }, (Directory directory) { - expect(findPackageConfig(directory), - throwsA(TypeMatcher())); + expect(findPackageConfig(directory), throwsA(isA())); }); fileTest('invalid .packages as INI', { @@ -144,8 +141,7 @@ void main() { 'package_config.json': packagesFile, } }, (Directory directory) { - expect(findPackageConfig(directory), - throwsA(TypeMatcher())); + expect(findPackageConfig(directory), throwsA(isA())); }); }); @@ -304,8 +300,8 @@ void main() { fileTest('no config found', {}, (Directory directory) { var file = dirFile(directory, 'anyname'); - expect(() => loadPackageConfig(file), - throwsA(TypeMatcher())); + expect( + () => loadPackageConfig(file), throwsA(isA())); }); fileTest('no config found, handled', {}, (Directory directory) async { diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index c8fbcb87c..b71ed5172 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -56,7 +56,7 @@ void main() { loaderTest('package_config.json', { '.packages': 'invalid .packages file', 'script.dart': 'main(){}', - 'packages': {'shouldNotBeFound': {}}, + 'packages': {'shouldNotBeFound': {}}, '.dart_tool': { 'package_config.json': packageConfigFile, } @@ -70,7 +70,7 @@ void main() { loaderTest('.packages', { '.packages': packagesFile, 'script.dart': 'main(){}', - 'packages': {'shouldNotBeFound': {}} + 'packages': {'shouldNotBeFound': {}} }, (directory, loader) async { var config = (await findPackageConfigUri(directory, loader: loader))!; expect(config.version, 1); // Found .packages file. @@ -107,7 +107,7 @@ void main() { // Does not find a packages/ directory, and returns null if nothing found. loaderTest('package directory packages not supported', { 'packages': { - 'foo': {}, + 'foo': {}, } }, (Uri directory, loader) async { var config = await findPackageConfigUri(directory, loader: loader); @@ -118,14 +118,14 @@ void main() { '.packages': 'not a .packages file', }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), - throwsA(TypeMatcher())); + throwsA(isA())); }); loaderTest('invalid .packages as JSON', { '.packages': packageConfigFile, }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), - throwsA(TypeMatcher())); + throwsA(isA())); }); loaderTest('invalid .packages', { @@ -134,7 +134,7 @@ void main() { } }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), - throwsA(TypeMatcher())); + throwsA(isA())); }); loaderTest('invalid .packages as INI', { @@ -143,7 +143,7 @@ void main() { } }, (Uri directory, loader) { expect(() => findPackageConfigUri(directory, loader: loader), - throwsA(TypeMatcher())); + throwsA(isA())); }); // Does not find .packages if no package_config.json and minVersion > 1. diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart index cef121713..87d1fd413 100644 --- a/pkgs/package_config/test/package_config_impl_test.dart +++ b/pkgs/package_config/test/package_config_impl_test.dart @@ -36,7 +36,7 @@ void main() { void failParse(String name, String input) { test('$name - error', () { expect(() => LanguageVersion.parse(input), - throwsA(TypeMatcher())); + throwsA(isA())); expect(() => LanguageVersion.parse(input), throwsFormatException); var failed = false; var actual = LanguageVersion.parse(input, onError: (_) { diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index ad4c74949..402fe8c42 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -53,7 +53,7 @@ void main() { test(name, () { expect( () => packages.parse(utf8.encode(content), baseFile, throwError), - throwsA(TypeMatcher())); + throwsA(isA())); }); test('$name, handle error', () { var hadError = false; @@ -308,7 +308,7 @@ void main() { // ignore: unnecessary_cast () => parsePackageConfigBytes(utf8.encode(source) as Uint8List, Uri.parse('file:///tmp/.dart_tool/file.dart'), throwError), - throwsA(TypeMatcher())); + throwsA(isA())); }); } diff --git a/pkgs/package_config/test/src/util.dart b/pkgs/package_config/test/src/util.dart index 246e12964..780ee80dc 100644 --- a/pkgs/package_config/test/src/util.dart +++ b/pkgs/package_config/test/src/util.dart @@ -28,7 +28,7 @@ ${packages.map((nu) => """ } """; -/// Mimics a directory structure of [description] and runs [fileTest]. +/// Mimics a directory structure of [description] and runs [loaderTest]. /// /// Description is a map, each key is a file entry. If the value is a map, /// it's a subdirectory, otherwise it's a file and the value is the content From 936e0cfb559180537679e56a46bb59b07f57e83c Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 10 Jan 2024 14:51:25 -0800 Subject: [PATCH 245/281] add test validating current behavior of packageOf, run CI on windows (dart-lang/package_config#137) - validates the behavior of https://github.com/dart-lang/package_config/issues/136 today (but does not change it) - removes build_runner deps for testing, there is no need to use it for such a small package - fixes a bug in discovery_test.dart that was probably landed due to inability to run tests --- .../.github/workflows/test-package.yml | 5 ++--- pkgs/package_config/pubspec.yaml | 3 --- pkgs/package_config/test/discovery_test.dart | 2 +- pkgs/package_config/test/parse_test.dart | 19 +++++++++++++++++++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 2e475912a..1768fc834 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -45,8 +45,7 @@ jobs: strategy: fail-fast: false matrix: - # Add macos-latest and/or windows-latest if relevant for this package. - os: [ubuntu-latest] + os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -57,5 +56,5 @@ jobs: name: Install dependencies run: dart pub get - name: Run tests - run: dart run build_runner test -- -p chrome,vm + run: dart test -p chrome,vm if: always() && steps.install.outcome == 'success' diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index b7130793f..6ac7f54dd 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -10,8 +10,5 @@ dependencies: path: ^1.8.0 dev_dependencies: - build_runner: ^2.0.0 - build_test: ^2.1.2 - build_web_compilers: ^4.0.0 dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index ee77559b1..2ca337a19 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -59,7 +59,7 @@ void main() { fileTest('package_config.json', { '.packages': 'invalid .packages file', 'script.dart': 'main(){}', - 'packages': {'shouldNotBeFound': {}}, + 'packages': {'shouldNotBeFound': {}}, '.dart_tool': { 'package_config.json': packageConfigFile, } diff --git a/pkgs/package_config/test/parse_test.dart b/pkgs/package_config/test/parse_test.dart index 402fe8c42..a92b9bfcc 100644 --- a/pkgs/package_config/test/parse_test.dart +++ b/pkgs/package_config/test/parse_test.dart @@ -301,6 +301,25 @@ void main() { Uri.parse('package:qux/diz')); }); + test('packageOf is case sensitive on windows', () { + var configBytes = utf8.encode(json.encode({ + 'configVersion': 2, + 'packages': [ + {'name': 'foo', 'rootUri': 'file:///C:/Foo/', 'packageUri': 'lib/'}, + ] + })); + var config = parsePackageConfigBytes( + // ignore: unnecessary_cast + configBytes as Uint8List, + Uri.parse('file:///C:/tmp/.dart_tool/file.dart'), + throwError); + expect(config.version, 2); + expect( + config.packageOf(Uri.parse('file:///C:/foo/lala/lala.dart')), null); + expect(config.packageOf(Uri.parse('file:///C:/Foo/lala/lala.dart'))!.name, + 'foo'); + }); + group('invalid', () { void testThrows(String name, String source) { test(name, () { From bd7c82be9b454b8bb44a7eef88e74bc4a49fa545 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 02:59:18 +0000 Subject: [PATCH 246/281] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/pool#80) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/pool#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/pool#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index b69f2bd51..23167a398 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 935c91e7617aaf72d8df1471400cb5c8eb52a6d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:17:20 +0000 Subject: [PATCH 247/281] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/package_config#146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 1768fc834..0fdbdeaf4 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.2, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From ec8a37c1468cfeec2b5c71217e29b1bfd89812f5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 28 Feb 2024 11:39:40 -0800 Subject: [PATCH 248/281] Latest lints, test wasm on dev channel (dart-lang/pool#81) --- pkgs/pool/.github/workflows/ci.yml | 3 + pkgs/pool/lib/pool.dart | 35 ++++++------ pkgs/pool/pubspec.yaml | 2 +- pkgs/pool/test/pool_test.dart | 88 +++++++++++++++--------------- 4 files changed, 67 insertions(+), 61 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 23167a398..d8339569b 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -62,3 +62,6 @@ jobs: - name: Run Chrome tests run: dart test --platform chrome if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests - wasm + run: dart test --platform chrome -c dart2wasm + if: always() && steps.install.outcome == 'success' && matrix.sdk == 'dev' diff --git a/pkgs/pool/lib/pool.dart b/pkgs/pool/lib/pool.dart index 20ab8f181..70e9df158 100644 --- a/pkgs/pool/lib/pool.dart +++ b/pkgs/pool/lib/pool.dart @@ -239,23 +239,26 @@ class Pool { /// an error, the returned future completes with that error. /// /// This may be called more than once; it returns the same [Future] each time. - Future close() => _closeMemo.runOnce(() { - if (_closeGroup != null) return _closeGroup!.future; + Future close() => _closeMemo.runOnce(_close); - _resetTimer(); + Future _close() { + if (_closeGroup != null) return _closeGroup!.future; - _closeGroup = FutureGroup(); - for (var callback in _onReleaseCallbacks) { - _closeGroup!.add(Future.sync(callback)); - } + _resetTimer(); - _allocatedResources -= _onReleaseCallbacks.length; - _onReleaseCallbacks.clear(); + _closeGroup = FutureGroup(); + for (var callback in _onReleaseCallbacks) { + _closeGroup!.add(Future.sync(callback)); + } + + _allocatedResources -= _onReleaseCallbacks.length; + _onReleaseCallbacks.clear(); + + if (_allocatedResources == 0) _closeGroup!.close(); + return _closeGroup!.future; + } - if (_allocatedResources == 0) _closeGroup!.close(); - return _closeGroup!.future; - }); - final _closeMemo = AsyncMemoizer(); + final _closeMemo = AsyncMemoizer(); /// If there are any pending requests, this will fire the oldest one. void _onResourceReleased() { @@ -272,7 +275,7 @@ class Pool { /// If there are any pending requests, this will fire the oldest one after /// running [onRelease]. - void _onResourceReleaseAllowed(Function() onRelease) { + void _onResourceReleaseAllowed(void Function() onRelease) { _resetTimer(); if (_requestedResources.isNotEmpty) { @@ -294,7 +297,7 @@ class Pool { /// /// Futures returned by [_runOnRelease] always complete in the order they were /// created, even if earlier [onRelease] callbacks take longer to run. - Future _runOnRelease(Function() onRelease) { + Future _runOnRelease(void Function() onRelease) { Future.sync(onRelease).then((value) { _onReleaseCompleters.removeFirst().complete(PoolResource._(this)); }).catchError((Object error, StackTrace stackTrace) { @@ -367,7 +370,7 @@ class PoolResource { /// This is useful when a resource's main function is complete, but it may /// produce additional information later on. For example, an isolate's task /// may be complete, but it could still emit asynchronous errors. - void allowRelease(Function() onRelease) { + void allowRelease(FutureOr Function() onRelease) { if (_released) { throw StateError('A PoolResource may only be released once.'); } diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 08e4027a9..7fb5021d3 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -13,6 +13,6 @@ dependencies: stack_trace: ^1.10.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 fake_async: ^1.2.0 test: ^1.16.0 diff --git a/pkgs/pool/test/pool_test.dart b/pkgs/pool/test/pool_test.dart index 2dd90f4a5..6334a8abd 100644 --- a/pkgs/pool/test/pool_test.dart +++ b/pkgs/pool/test/pool_test.dart @@ -41,7 +41,7 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - Future.delayed(const Duration(microseconds: 1)).then((_) { + Future.delayed(const Duration(microseconds: 1)).then((_) { lastAllocatedResource.release(); }); }); @@ -55,7 +55,7 @@ void main() { test('can be called freely up to the limit', () { var pool = Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync0(() => Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } }); @@ -63,7 +63,7 @@ void main() { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 50; i++) { - pool.withResource(expectAsync0(() => Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } pool.withResource(expectNoAsync()); @@ -75,20 +75,20 @@ void main() { FakeAsync().run((async) { var pool = Pool(50); for (var i = 0; i < 49; i++) { - pool.withResource(expectAsync0(() => Completer().future)); + pool.withResource(expectAsync0(() => Completer().future)); } - var completer = Completer(); + var completer = Completer(); pool.withResource(() => completer.future); var blockedResourceAllocated = false; pool.withResource(() { blockedResourceAllocated = true; }); - Future.delayed(const Duration(microseconds: 1)).then((_) { + Future.delayed(const Duration(microseconds: 1)).then((_) { expect(blockedResourceAllocated, isFalse); completer.complete(); - return Future.delayed(const Duration(microseconds: 1)); + return Future.delayed(const Duration(microseconds: 1)); }).then((_) { expect(blockedResourceAllocated, isTrue); }); @@ -128,7 +128,7 @@ void main() { // This will only complete once [lastAllocatedResource] is released. expect(pool.request(), completes); - Future.delayed(const Duration(seconds: 3)).then((_) { + Future.delayed(const Duration(seconds: 3)).then((_) { lastAllocatedResource.release(); expect(pool.request(), doesNotComplete); }); @@ -146,7 +146,7 @@ void main() { } expect(pool.request(), doesNotComplete); - Future.delayed(const Duration(seconds: 3)).then((_) { + Future.delayed(const Duration(seconds: 3)).then((_) { expect(pool.request(), doesNotComplete); }); @@ -177,11 +177,11 @@ void main() { var resource = await pool.request(); var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isFalse); expect(pool.request(), completes); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); @@ -195,7 +195,7 @@ void main() { var onReleaseCalled = false; resource.allowRelease(() => onReleaseCalled = true); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onReleaseCalled, isTrue); }); @@ -206,13 +206,13 @@ void main() { var requestComplete = false; unawaited(pool.request().then((_) => requestComplete = true)); - var completer = Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(requestComplete, isFalse); completer.complete(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(requestComplete, isTrue); }); @@ -228,21 +228,21 @@ void main() { unawaited(pool.request().then((_) => request2Complete = true)); var onRelease1Called = false; - var completer1 = Completer(); + var completer1 = Completer(); resource1.allowRelease(() { onRelease1Called = true; return completer1.future; }); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onRelease1Called, isTrue); var onRelease2Called = false; - var completer2 = Completer(); + var completer2 = Completer(); resource2.allowRelease(() { onRelease2Called = true; return completer2.future; }); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(onRelease2Called, isTrue); expect(request1Complete, isFalse); expect(request2Complete, isFalse); @@ -251,12 +251,12 @@ void main() { // was triggered by the second blocking request, it should complete the // first one to preserve ordering. completer2.complete(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isFalse); completer1.complete(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); expect(request1Complete, isTrue); expect(request2Complete, isTrue); }); @@ -286,7 +286,7 @@ void main() { var resource = await pool.request(); resource.release(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); }); group('close()', () { @@ -313,7 +313,7 @@ void main() { var pool = Pool(1); var resource1 = await pool.request(); - var completer = Completer(); + var completer = Completer(); expect( pool.request().then((resource2) { expect(completer.isCompleted, isTrue); @@ -323,7 +323,7 @@ void main() { expect(pool.close(), completes); resource1.allowRelease(() => completer.future); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); @@ -347,11 +347,11 @@ void main() { resource1Released = true; resource1.release(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); resource2Released = true; resource2.release(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); var resource3 = await resource3Future; resource3Released = true; @@ -364,7 +364,7 @@ void main() { // Set up an onRelease callback whose completion is controlled by // [completer]. - var completer = Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); expect( pool.request().then((_) { @@ -372,10 +372,10 @@ void main() { }), completes); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); unawaited(pool.close()); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); @@ -384,9 +384,9 @@ void main() { var resource1 = await pool.request(); var resource2 = await pool.request(); - var completer1 = Completer(); + var completer1 = Completer(); resource1.allowRelease(() => completer1.future); - var completer2 = Completer(); + var completer2 = Completer(); resource2.allowRelease(() => completer2.future); expect( @@ -396,10 +396,10 @@ void main() { }), completes); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer1.complete(); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer2.complete(); }); @@ -407,17 +407,17 @@ void main() { var pool = Pool(1); var resource = await pool.request(); - var completer = Completer(); + var completer = Completer(); expect( pool.close().then((_) { expect(completer.isCompleted, isTrue); }), completes); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); resource.allowRelease(() => completer.future); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.complete(); }); @@ -425,13 +425,13 @@ void main() { var pool = Pool(1); var resource = await pool.request(); - var completer = Completer(); + var completer = Completer(); resource.allowRelease(() => completer.future); expect(pool.done, throwsA('oh no!')); expect(pool.close(), throwsA('oh no!')); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); completer.completeError('oh no!'); }); }); @@ -446,7 +446,7 @@ void main() { const delayedToStringDuration = Duration(milliseconds: 10); Future delayedToString(int i) => - Future.delayed(delayedToStringDuration, () => i.toString()); + Future.delayed(delayedToStringDuration, () => i.toString()); for (var itemCount in [0, 5]) { for (var poolSize in [1, 5, 6]) { @@ -505,7 +505,7 @@ void main() { 'before the entire iterable is iterated.'); return i; }), (i) async { - await Future.delayed(Duration(milliseconds: i)); + await Future.delayed(Duration(milliseconds: i)); return i; }); @@ -585,7 +585,7 @@ void main() { pool.close(); }); - await subscription.asFuture(); + await subscription.asFuture(); expect(dataCount, 100); await subscription.cancel(); }); @@ -616,7 +616,7 @@ void main() { if (int.parse(data) % 3 == 1) { subscription.pause(Future(() async { - await Future.delayed(const Duration(milliseconds: 100)); + await Future.delayed(const Duration(milliseconds: 100)); })); } }, @@ -690,7 +690,7 @@ void main() { pool = Pool(20); var listFuture = pool.forEach(Iterable.generate(100), (i) async { - await Future.delayed(const Duration(milliseconds: 10)); + await Future.delayed(const Duration(milliseconds: 10)); if (i == 10) { throw UnsupportedError('10 is not supported'); } @@ -705,7 +705,7 @@ void main() { var list = await pool.forEach(Iterable.generate(100), (int i) async { - await Future.delayed(const Duration(milliseconds: 10)); + await Future.delayed(const Duration(milliseconds: 10)); if (i % 10 == 0) { throw UnsupportedError('Multiples of 10 not supported'); } From bff0401456cb06981c345e875ecd370be66c302a Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Tue, 5 Mar 2024 01:20:14 +0100 Subject: [PATCH 249/281] Fix typo (dart-lang/package_config#149) --- pkgs/package_config/lib/src/package_config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index c00ac67af..048555fc1 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -26,7 +26,7 @@ abstract class PackageConfig { /// is expected, but none have been specified or found. static const PackageConfig empty = SimplePackageConfig.empty(); - /// Creats a package configuration with the provided available [packages]. + /// Creates a package configuration with the provided available [packages]. /// /// The packages must be valid packages (valid package name, valid /// absolute directory URIs, valid language version, if any), From 0bc41a970f77296d99cfe435edf16545e69fa069 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 02:59:29 +0000 Subject: [PATCH 250/281] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/pool#82) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index d8339569b..7d9adb67b 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From b9ca0553113924fffba7b6d8b2879e775d3ce5e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 20:35:07 +0000 Subject: [PATCH 251/281] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/package_config#150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 0fdbdeaf4..88c5dffee 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 84b8800af21e24663d24dfab239d5cac4fbe2984 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Thu, 11 Apr 2024 08:56:47 +0200 Subject: [PATCH 252/281] Fix typos. (dart-lang/package_config#147) The wonders of in-IDE spell checking. Also ask for newest lints (no changes needed). --- pkgs/package_config/CHANGELOG.md | 2 +- pkgs/package_config/lib/src/discovery.dart | 8 ++++---- pkgs/package_config/lib/src/package_config.dart | 6 +++--- pkgs/package_config/lib/src/package_config_impl.dart | 2 +- pkgs/package_config/lib/src/packages_file.dart | 2 +- pkgs/package_config/lib/src/util.dart | 2 +- pkgs/package_config/pubspec.yaml | 2 +- pkgs/package_config/test/package_config_impl_test.dart | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index a682bc3a4..2870c8c08 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -53,7 +53,7 @@ - Based on new JSON file format with more content. - This version includes all the new functionality intended for a 2.0.0 version, as well as the, now deprecated, version 1 functionality. - When we release 2.0.0, the deprectated functionality will be removed. + When we release 2.0.0, the deprecated functionality will be removed. ## 1.1.0 diff --git a/pkgs/package_config/lib/src/discovery.dart b/pkgs/package_config/lib/src/discovery.dart index 352bed8ca..b67841099 100644 --- a/pkgs/package_config/lib/src/discovery.dart +++ b/pkgs/package_config/lib/src/discovery.dart @@ -33,7 +33,7 @@ final Uri parentPath = Uri(path: '..'); /// Returns `null` if no configuration was found. If a configuration /// is needed, then the caller can supply [PackageConfig.empty]. /// -/// If [minVersion] is greated than 1, `.packages` files are ignored. +/// If [minVersion] is greater than 1, `.packages` files are ignored. /// If [minVersion] is greater than the version read from the /// `package_config.json` file, it too is ignored. Future findPackageConfig(Directory baseDirectory, @@ -46,7 +46,7 @@ Future findPackageConfig(Directory baseDirectory, do { // Check for $cwd/.packages var packageConfig = - await findPackagConfigInDirectory(directory, minVersion, onError); + await findPackageConfigInDirectory(directory, minVersion, onError); if (packageConfig != null) return packageConfig; if (!recursive) break; // Check in parent directories. @@ -113,10 +113,10 @@ Future findPackageConfigUri( /// a best-effort attempt is made to return a package configuration. /// This may be the empty package configuration. /// -/// If [minVersion] is greated than 1, `.packages` files are ignored. +/// If [minVersion] is greater than 1, `.packages` files are ignored. /// If [minVersion] is greater than the version read from the /// `package_config.json` file, it too is ignored. -Future findPackagConfigInDirectory(Directory directory, +Future findPackageConfigInDirectory(Directory directory, int minVersion, void Function(Object error) onError) async { var packageConfigFile = await checkForPackageConfigJsonFile(directory); if (packageConfigFile != null) { diff --git a/pkgs/package_config/lib/src/package_config.dart b/pkgs/package_config/lib/src/package_config.dart index 048555fc1..155dfc539 100644 --- a/pkgs/package_config/lib/src/package_config.dart +++ b/pkgs/package_config/lib/src/package_config.dart @@ -34,7 +34,7 @@ abstract class PackageConfig { /// /// The package's root ([Package.root]) and package-root /// ([Package.packageUriRoot]) paths must satisfy a number of constraints - /// We say that one path (which we know ends with a `/` charater) + /// We say that one path (which we know ends with a `/` character) /// is inside another path, if the latter path is a prefix of the former path, /// including the two paths being the same. /// @@ -159,7 +159,7 @@ abstract class PackageConfig { /// Look up a package by name. /// - /// Returns the [Package] fron [packages] with [packageName] as + /// Returns the [Package] from [packages] with [packageName] as /// [Package.name]. Returns `null` if the package is not available in the /// current configuration. Package? operator [](String packageName); @@ -377,7 +377,7 @@ abstract class LanguageVersion implements Comparable { /// An *invalid* language version. /// -/// Stored in a [Package] when the orginal language version string +/// Stored in a [Package] when the original language version string /// was invalid and a `onError` handler was passed to the parser /// which did not throw on an error. abstract class InvalidLanguageVersion implements LanguageVersion { diff --git a/pkgs/package_config/lib/src/package_config_impl.dart b/pkgs/package_config/lib/src/package_config_impl.dart index d8e8d495f..865e99a8e 100644 --- a/pkgs/package_config/lib/src/package_config_impl.dart +++ b/pkgs/package_config/lib/src/package_config_impl.dart @@ -436,7 +436,7 @@ class TriePackageTree implements PackageTree { } // For internal reasons we allow this (for now). One should still never do - // it thouh. + // it though. // 3) The new package is inside the packageUriRoot of existing package. if (_disallowPackagesInsidePackageUriRoot) { if (_beginsWith(0, existingPackage.packageUriRoot.toString(), diff --git a/pkgs/package_config/lib/src/packages_file.dart b/pkgs/package_config/lib/src/packages_file.dart index f84db1075..bf68f2c88 100644 --- a/pkgs/package_config/lib/src/packages_file.dart +++ b/pkgs/package_config/lib/src/packages_file.dart @@ -114,7 +114,7 @@ PackageConfig parse( } if (packageNames.contains(packageName)) { onError(PackageConfigFormatException( - 'Same package name occured more than once', source, start)); + 'Same package name occurred more than once', source, start)); continue; } var rootUri = packageLocation; diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index 3bf1bece3..f1fa20790 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -164,7 +164,7 @@ bool hasAbsolutePath(Uri uri) => /// the [baseUri], or if there is no overlap in the paths of the /// two URIs at all, the [uri] is returned as-is. /// -/// Otherwise the result is a path-only URI which satsifies +/// Otherwise the result is a path-only URI which satisfies /// `baseUri.resolveUri(result) == uri`, /// /// The `baseUri` must be absolute. diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 6ac7f54dd..9db82c64f 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -10,5 +10,5 @@ dependencies: path: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^2.1.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/package_config_impl_test.dart b/pkgs/package_config/test/package_config_impl_test.dart index 87d1fd413..0f399636f 100644 --- a/pkgs/package_config/test/package_config_impl_test.dart +++ b/pkgs/package_config/test/package_config_impl_test.dart @@ -126,7 +126,7 @@ void main() { }); group('package config', () { - test('emtpy', () { + test('empty', () { var empty = PackageConfig([], extraData: unique); expect(empty.version, 2); expect(empty.packages, isEmpty); From 98f8a511fe2fddada504ef181450541f1edd7ea6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 02:59:00 +0000 Subject: [PATCH 253/281] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/pool#83) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 7d9adb67b..53f1fe9e5 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 60b7a2ce9151bddec3411653728eb28ea4e0ce7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:26:07 +0000 Subject: [PATCH 254/281] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/pool#84) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 53f1fe9e5..9ff1a9574 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 1f2920db3e8b68eda3990e1607628d81b2554b47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 20:46:46 +0000 Subject: [PATCH 255/281] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/package_config#152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 88c5dffee..9196439e4 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.2, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 709cf70e99fbae9fd38659f69d81e8823eab3bb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 02:58:43 +0000 Subject: [PATCH 256/281] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/package_config#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 9196439e4..2c2893435 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 84d468b6f9fa47635864ba9574ac16266dc69220 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 9 May 2024 08:39:57 -0700 Subject: [PATCH 257/281] blast_repo fixes (dart-lang/pool#85) dependabot --- pkgs/pool/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/pool/.github/dependabot.yml b/pkgs/pool/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/pool/.github/dependabot.yml +++ b/pkgs/pool/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From d8e1a5e62ff78f24c271355123c24def035403b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 15:42:13 +0000 Subject: [PATCH 258/281] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/pool#86) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 9ff1a9574..53338d55b 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From bc259463ae9bc33de667734b7d802eec7aeaec0e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 9 May 2024 13:46:44 -0700 Subject: [PATCH 259/281] blast_repo fixes (dart-lang/package_config#153) dependabot --- pkgs/package_config/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/package_config/.github/dependabot.yml b/pkgs/package_config/.github/dependabot.yml index c84404dc9..a19a66adf 100644 --- a/pkgs/package_config/.github/dependabot.yml +++ b/pkgs/package_config/.github/dependabot.yml @@ -10,3 +10,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 4031629a7ed3eaae045bab1a1b0313d9b2539a3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 20:53:27 +0000 Subject: [PATCH 260/281] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/package_config#154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 2c2893435..c9d757965 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 80670e18721ea8f36b8fba01591cd416b94eaa20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 20:59:14 +0000 Subject: [PATCH 261/281] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/package_config#155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index c9d757965..3fd2c820b 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From f541e0fc6431a1f28349e0408d64c4bdfe50e6b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Jun 2024 18:18:59 +0000 Subject: [PATCH 262/281] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/pool#87) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 53338d55b..be844e630 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From dbfe2da00ecc026feee71b9c15dee387724daf3c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Jun 2024 13:04:55 -0700 Subject: [PATCH 263/281] blast_repo fixes (dart-lang/pool#88) auto-publish, github-actions, no-response --- pkgs/pool/.github/workflows/ci.yml | 4 ++-- pkgs/pool/.github/workflows/publish.yaml | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index be844e630..63d902e4b 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} diff --git a/pkgs/pool/.github/workflows/publish.yaml b/pkgs/pool/.github/workflows/publish.yaml index fcb7ccb89..27157a046 100644 --- a/pkgs/pool/.github/workflows/publish.yaml +++ b/pkgs/pool/.github/workflows/publish.yaml @@ -6,9 +6,12 @@ on: pull_request: branches: [ master ] push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] jobs: publish: if: ${{ github.repository_owner == 'dart-lang' }} uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From 6aaa80bc0ab2ab9cf54521031a847d2bcbae3bc8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 21 Jun 2024 16:22:00 -0700 Subject: [PATCH 264/281] update lints, require Dart 3.4 (dart-lang/pool#89) --- pkgs/pool/.github/workflows/ci.yml | 2 +- pkgs/pool/CHANGELOG.md | 2 +- pkgs/pool/pubspec.yaml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 63d902e4b..a411e90e0 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index e17e848cc..4c1e72ddd 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.5.2-wip -* Require Dart 3.0. +* Require Dart 3.4. ## 1.5.1 diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 7fb5021d3..4ad49c264 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -6,13 +6,13 @@ description: >- repository: https://github.com/dart-lang/pool environment: - sdk: ^3.0.0 + sdk: ^3.4.0 dependencies: async: ^2.5.0 stack_trace: ^1.10.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 fake_async: ^1.2.0 - test: ^1.16.0 + test: ^1.16.6 From 1e12b0dd164afa4293f5ef018a6d56480059e862 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 02:23:00 +0000 Subject: [PATCH 265/281] Bump dart-lang/setup-dart in the github-actions group (dart-lang/pool#90) Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/pool#118: dart-lang/setup-dartdart-lang/pool#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/pool#118: dart-lang/setup-dartdart-lang/pool#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.4&new-version=1.6.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index a411e90e0..d99a64cd6 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 58f90e988ff570a86be87da2631fe345aed60d5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:38:26 +0000 Subject: [PATCH 266/281] Bump the github-actions group with 2 updates (dart-lang/package_config#156) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/package_config#118: dart-lang/setup-dartdart-lang/package_config#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/package_config#118: dart-lang/setup-dartdart-lang/package_config#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 3fd2c820b..33717105d 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -48,8 +48,8 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 5bfdcd8e92db637a134f188e5204b970b306c79c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 6 Aug 2024 09:04:47 -0700 Subject: [PATCH 267/281] Latest lints, require Dart 3.4 (dart-lang/package_config#157) --- pkgs/package_config/.github/workflows/test-package.yml | 2 +- pkgs/package_config/CHANGELOG.md | 2 +- pkgs/package_config/lib/package_config.dart | 2 +- pkgs/package_config/lib/package_config_types.dart | 2 +- pkgs/package_config/lib/src/util.dart | 2 +- pkgs/package_config/lib/src/util_io.dart | 2 +- pkgs/package_config/pubspec.yaml | 4 ++-- pkgs/package_config/test/discovery_test.dart | 2 +- pkgs/package_config/test/discovery_uri_test.dart | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 33717105d..704ee2e3c 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] - sdk: [3.2, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 2870c8c08..f9fec1d00 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.1.1-wip -- Require Dart 3.2 +- Require Dart 3.4 ## 2.1.0 diff --git a/pkgs/package_config/lib/package_config.dart b/pkgs/package_config/lib/package_config.dart index 194fe894e..074c97707 100644 --- a/pkgs/package_config/lib/package_config.dart +++ b/pkgs/package_config/lib/package_config.dart @@ -7,7 +7,7 @@ /// /// This package provides functionality to find, read and write package /// configurations in the [specified format](https://github.com/dart-lang/language/blob/master/accepted/future-releases/language-versioning/package-config-file-v2.md). -library package_config.package_config; +library; import 'dart:io' show Directory, File; import 'dart:typed_data' show Uint8List; diff --git a/pkgs/package_config/lib/package_config_types.dart b/pkgs/package_config/lib/package_config_types.dart index 756be0518..825f7acec 100644 --- a/pkgs/package_config/lib/package_config_types.dart +++ b/pkgs/package_config/lib/package_config_types.dart @@ -10,7 +10,7 @@ /// {@canonicalFor package_config.Package} /// {@canonicalFor package_config.PackageConfig} /// {@canonicalFor errors.PackageConfigError} -library package_config.package_config_types; +library; export 'src/errors.dart' show PackageConfigError; export 'src/package_config.dart' diff --git a/pkgs/package_config/lib/src/util.dart b/pkgs/package_config/lib/src/util.dart index f1fa20790..4f0210cda 100644 --- a/pkgs/package_config/lib/src/util.dart +++ b/pkgs/package_config/lib/src/util.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Utility methods used by more than one library in the package. -library package_config.util; +library; import 'errors.dart'; diff --git a/pkgs/package_config/lib/src/util_io.dart b/pkgs/package_config/lib/src/util_io.dart index 914ea384e..4680eefd4 100644 --- a/pkgs/package_config/lib/src/util_io.dart +++ b/pkgs/package_config/lib/src/util_io.dart @@ -4,7 +4,7 @@ /// Utility methods requiring dart:io and used by more than one library in the /// package. -library package_config.util_io; +library; import 'dart:io'; import 'dart:typed_data'; diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 9db82c64f..545701d6d 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -4,11 +4,11 @@ description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/package_config environment: - sdk: ^3.2.0 + sdk: ^3.4.0 dependencies: path: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.1.0 + dart_flutter_team_lints: ^3.0.0 test: ^1.16.0 diff --git a/pkgs/package_config/test/discovery_test.dart b/pkgs/package_config/test/discovery_test.dart index 2ca337a19..6d1b65529 100644 --- a/pkgs/package_config/test/discovery_test.dart +++ b/pkgs/package_config/test/discovery_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') -library package_config.discovery_test; +library; import 'dart:io'; diff --git a/pkgs/package_config/test/discovery_uri_test.dart b/pkgs/package_config/test/discovery_uri_test.dart index b71ed5172..542bf0a65 100644 --- a/pkgs/package_config/test/discovery_uri_test.dart +++ b/pkgs/package_config/test/discovery_uri_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') -library package_config.discovery_test; +library; import 'package:package_config/package_config.dart'; import 'package:test/test.dart'; From 3b5c3516779f6bec9bb5374966674841a46172f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:49:51 +0000 Subject: [PATCH 268/281] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/package_config#159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 704ee2e3c..629a95d64 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From b6a8e6878181d537b3aa25851608f33a5c622305 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:20:50 +0000 Subject: [PATCH 269/281] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/pool#91) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index d99a64cd6..34a41d3d5 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From ff6870b6b6bc77a53ac6fae3fc0fc699bb071d1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 02:23:07 +0000 Subject: [PATCH 270/281] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/pool#92) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index 34a41d3d5..a58ee8b89 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 34d75539e5838239d12b3d3b548c6c82d16465e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 20:39:05 +0000 Subject: [PATCH 271/281] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/package_config#160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 629a95d64..526e05593 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, windows-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From ecc44a110ae6ad676a8d2e018d44c7fe1a740066 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:02:14 +0000 Subject: [PATCH 272/281] Bump dart-lang/setup-dart in the github-actions group (dart-lang/pool#93) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/pool#118: dart-lang/setup-dartdart-lang/pool#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pool/.github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/.github/workflows/ci.yml b/pkgs/pool/.github/workflows/ci.yml index a58ee8b89..cf5a84e83 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/pkgs/pool/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From adca221376fef5545f3a997c8004aba8780ce0b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 20:07:57 +0000 Subject: [PATCH 273/281] Bump dart-lang/setup-dart in the github-actions group (dart-lang/package_config#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/package_config#118: dart-lang/setup-dartdart-lang/package_config#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/package_config/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/pkgs/package_config/.github/workflows/test-package.yml index 526e05593..718ec07b8 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/pkgs/package_config/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From a9b1487e63fe99389ff269eaee7c5a9653566b9d Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 9 Dec 2024 16:56:09 +0100 Subject: [PATCH 274/281] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/package_config.md | 5 ++++ pkgs/package_config/CONTRIBUTING.md | 33 ------------------------ pkgs/package_config/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/package_config.md delete mode 100644 pkgs/package_config/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/package_config.md b/.github/ISSUE_TEMPLATE/package_config.md new file mode 100644 index 000000000..f6322d0fa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/package_config.md @@ -0,0 +1,5 @@ +--- +name: "package:package_config" +about: "Create a bug or file a feature request against package:package_config." +labels: "package:package_config" +--- \ No newline at end of file diff --git a/pkgs/package_config/CONTRIBUTING.md b/pkgs/package_config/CONTRIBUTING.md deleted file mode 100644 index 8423ff94f..000000000 --- a/pkgs/package_config/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // Copyright (c) 2019, 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 545701d6d..5e1356b02 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,7 +1,7 @@ name: package_config version: 2.1.1-wip description: Support for reading and writing Dart Package Configuration files. -repository: https://github.com/dart-lang/package_config +repository: https://github.com/dart-lang/tools/tree/main/pkgs/package_config environment: sdk: ^3.4.0 From 3327cbf89b56b0234fd4da728f1f181394609b1a Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 11:33:46 +0100 Subject: [PATCH 275/281] Moving fixes --- .github/labeler.yml | 4 ++++ .../workflows/package_config.yaml | 17 ++++++++++++++--- README.md | 1 + pkgs/package_config/.github/dependabot.yml | 16 ---------------- pkgs/package_config/CHANGELOG.md | 1 + pkgs/package_config/README.md | 2 +- pkgs/package_config/pubspec.yaml | 2 +- 7 files changed, 22 insertions(+), 21 deletions(-) rename pkgs/package_config/.github/workflows/test-package.yml => .github/workflows/package_config.yaml (83%) delete mode 100644 pkgs/package_config/.github/dependabot.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 45c2239b1..31b8b4733 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -76,6 +76,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/oauth2/**' +'package:package_config': + - changed-files: + - any-glob-to-any-file: 'pkgs/package_config/**' + 'package:source_map_stack_trace': - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' diff --git a/pkgs/package_config/.github/workflows/test-package.yml b/.github/workflows/package_config.yaml similarity index 83% rename from pkgs/package_config/.github/workflows/test-package.yml rename to .github/workflows/package_config.yaml index 718ec07b8..416ea1a11 100644 --- a/pkgs/package_config/.github/workflows/test-package.yml +++ b/.github/workflows/package_config.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:package_config on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/package_config.yml' + - 'pkgs/package_config/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/package_config.yml' + - 'pkgs/package_config/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/package_config/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index ed90416dd..01360e92b 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ don't naturally belong to other topic monorepos (like | [json_rpc_2](pkgs/json_rpc_2/) | Utilities to write a client or server using the JSON-RPC 2.0 spec. | [![package issues](https://img.shields.io/badge/package:json_rpc_2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ajson_rpc_2) | [![pub package](https://img.shields.io/pub/v/json_rpc_2.svg)](https://pub.dev/packages/json_rpc_2) | | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | +| [package_config](pkgs/package_config/) | Support for reading and writing Dart Package Configuration files. | [![package issues](https://img.shields.io/badge/package:package_config-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apackage_config) | [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | diff --git a/pkgs/package_config/.github/dependabot.yml b/pkgs/package_config/.github/dependabot.yml deleted file mode 100644 index a19a66adf..000000000 --- a/pkgs/package_config/.github/dependabot.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - -version: 2 -updates: - -- package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index f9fec1d00..93033ed6e 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.1.1-wip - Require Dart 3.4 +- Move to `dart-lang/tools` monorepo. ## 2.1.0 diff --git a/pkgs/package_config/README.md b/pkgs/package_config/README.md index 9e2e41f0b..76fd3cbed 100644 --- a/pkgs/package_config/README.md +++ b/pkgs/package_config/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://github.com/dart-lang/package_config/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/package_config/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/package_config.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/package_config.yaml) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) [![package publisher](https://img.shields.io/pub/publisher/package_config.svg)](https://pub.dev/packages/package_config/publisher) diff --git a/pkgs/package_config/pubspec.yaml b/pkgs/package_config/pubspec.yaml index 5e1356b02..28f3e1364 100644 --- a/pkgs/package_config/pubspec.yaml +++ b/pkgs/package_config/pubspec.yaml @@ -1,5 +1,5 @@ name: package_config -version: 2.1.1-wip +version: 2.1.1 description: Support for reading and writing Dart Package Configuration files. repository: https://github.com/dart-lang/tools/tree/main/pkgs/package_config From 3655677c5fa2af487a2d443282266cda0ef1f193 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 14:03:01 +0100 Subject: [PATCH 276/281] Remove wip --- pkgs/package_config/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/package_config/CHANGELOG.md b/pkgs/package_config/CHANGELOG.md index 93033ed6e..101a0fe76 100644 --- a/pkgs/package_config/CHANGELOG.md +++ b/pkgs/package_config/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.1.1-wip +## 2.1.1 - Require Dart 3.4 - Move to `dart-lang/tools` monorepo. From 92f34c920bb9d5bf47c01965ca994c2b5ed489f0 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 14:05:52 +0100 Subject: [PATCH 277/281] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/pool.md | 5 +++++ pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/pool.md diff --git a/.github/ISSUE_TEMPLATE/pool.md b/.github/ISSUE_TEMPLATE/pool.md new file mode 100644 index 000000000..7af32c4a6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/pool.md @@ -0,0 +1,5 @@ +--- +name: "package:pool" +about: "Create a bug or file a feature request against package:pool." +labels: "package:pool" +--- \ No newline at end of file diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 4ad49c264..a205b7494 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.5.2-wip description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. -repository: https://github.com/dart-lang/pool +repository: https://github.com/dart-lang/tools/tree/main/pkgs/pool environment: sdk: ^3.4.0 From 8ab3ea92a5dc50dabf495fc8bf8215a52d8baee1 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 14:14:37 +0100 Subject: [PATCH 278/281] merge fixes --- .github/labeler.yml | 4 ++ .../ci.yml => .github/workflows/pool.yaml | 17 +++++++-- README.md | 1 + pkgs/pool/.github/dependabot.yml | 15 -------- pkgs/pool/.github/workflows/no-response.yml | 37 ------------------- pkgs/pool/.github/workflows/publish.yaml | 17 --------- pkgs/pool/CHANGELOG.md | 3 +- pkgs/pool/README.md | 2 +- pkgs/pool/benchmark/for_each_benchmark.dart | 20 ++++++---- pkgs/pool/pubspec.yaml | 2 +- 10 files changed, 36 insertions(+), 82 deletions(-) rename pkgs/pool/.github/workflows/ci.yml => .github/workflows/pool.yaml (88%) delete mode 100644 pkgs/pool/.github/dependabot.yml delete mode 100644 pkgs/pool/.github/workflows/no-response.yml delete mode 100644 pkgs/pool/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index eca80bbc2..88d513756 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -80,6 +80,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/oauth2/**' +'package:pool': + - changed-files: + - any-glob-to-any-file: 'pkgs/pool/**' + 'package:source_map_stack_trace': - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' diff --git a/pkgs/pool/.github/workflows/ci.yml b/.github/workflows/pool.yaml similarity index 88% rename from pkgs/pool/.github/workflows/ci.yml rename to .github/workflows/pool.yaml index cf5a84e83..6d64062a8 100644 --- a/pkgs/pool/.github/workflows/ci.yml +++ b/.github/workflows/pool.yaml @@ -1,17 +1,28 @@ -name: CI +name: package:pool on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/pool.yaml' + - 'pkgs/pool/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/pool.yaml' + - 'pkgs/pool/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/pool/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 50517c36e..9d938393f 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ don't naturally belong to other topic monorepos (like | [json_rpc_2](pkgs/json_rpc_2/) | Utilities to write a client or server using the JSON-RPC 2.0 spec. | [![package issues](https://img.shields.io/badge/package:json_rpc_2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ajson_rpc_2) | [![pub package](https://img.shields.io/pub/v/json_rpc_2.svg)](https://pub.dev/packages/json_rpc_2) | | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | +| [pool](pkgs/pool/) | Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. | [![package issues](https://img.shields.io/badge/package:pool-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apool) | [![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | diff --git a/pkgs/pool/.github/dependabot.yml b/pkgs/pool/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/pool/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/pool/.github/workflows/no-response.yml b/pkgs/pool/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/pool/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/pool/.github/workflows/publish.yaml b/pkgs/pool/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046..000000000 --- a/pkgs/pool/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index 4c1e72ddd..d7ab9abed 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,6 +1,7 @@ -## 1.5.2-wip +## 1.5.2 * Require Dart 3.4. +* Move to `dart-lang/tools` monorepo. ## 1.5.1 diff --git a/pkgs/pool/README.md b/pkgs/pool/README.md index b100ed35d..461e872b8 100644 --- a/pkgs/pool/README.md +++ b/pkgs/pool/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/pool/actions/workflows/ci.yml/badge.svg)](https://github.com/dart-lang/pool/actions/workflows/ci.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/pool.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/pool.yaml) [![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) [![package publisher](https://img.shields.io/pub/publisher/pool.svg)](https://pub.dev/packages/pool/publisher) diff --git a/pkgs/pool/benchmark/for_each_benchmark.dart b/pkgs/pool/benchmark/for_each_benchmark.dart index 2973b2a36..8a0c7834a 100644 --- a/pkgs/pool/benchmark/for_each_benchmark.dart +++ b/pkgs/pool/benchmark/for_each_benchmark.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2024, 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. + import 'package:pool/pool.dart'; void main(List args) async { @@ -19,18 +23,20 @@ void main(List args) async { lastLog == null || now.difference(lastLog!) > const Duration(seconds: 1)) { lastLog = now; - print([ - now.difference(start), - i.toString().padLeft(10), - fastestIteration.toString().padLeft(7), - fastest!.inMicroseconds.toString().padLeft(9) - ].join(' ')); + print( + [ + now.difference(start), + i.toString().padLeft(10), + fastestIteration.toString().padLeft(7), + fastest!.inMicroseconds.toString().padLeft(9), + ].join(' '), + ); } } print(['Elapsed ', 'Iterations', 'Fastest', 'Time (us)'].join(' ')); - for (;; i++) { + for (; ; i++) { watch.reset(); var sum = await pool diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index a205b7494..4af8a71d2 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.2-wip +version: 1.5.2 description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. From 065fd6c8315671d29921eae62e37d346038b37d5 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 14:36:32 +0100 Subject: [PATCH 279/281] unformat --- pkgs/pool/benchmark/for_each_benchmark.dart | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/pkgs/pool/benchmark/for_each_benchmark.dart b/pkgs/pool/benchmark/for_each_benchmark.dart index 8a0c7834a..0cd2543e2 100644 --- a/pkgs/pool/benchmark/for_each_benchmark.dart +++ b/pkgs/pool/benchmark/for_each_benchmark.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2024, 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. @@ -23,20 +23,18 @@ void main(List args) async { lastLog == null || now.difference(lastLog!) > const Duration(seconds: 1)) { lastLog = now; - print( - [ - now.difference(start), - i.toString().padLeft(10), - fastestIteration.toString().padLeft(7), - fastest!.inMicroseconds.toString().padLeft(9), - ].join(' '), - ); + print([ + now.difference(start), + i.toString().padLeft(10), + fastestIteration.toString().padLeft(7), + fastest!.inMicroseconds.toString().padLeft(9) + ].join(' ')); } } print(['Elapsed ', 'Iterations', 'Fastest', 'Time (us)'].join(' ')); - for (; ; i++) { + for (;; i++) { watch.reset(); var sum = await pool From 28160af6c894c14867a4a8b23e3c45205a079e09 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 10:13:42 +0100 Subject: [PATCH 280/281] Upgrade major version --- pkgs/pool/CHANGELOG.md | 2 +- pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index d7ab9abed..e9f37916b 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.5.2 +## 2.0.0 * Require Dart 3.4. * Move to `dart-lang/tools` monorepo. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 4af8a71d2..7e6271226 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 1.5.2 +version: 2.0.0 description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. From 01ef2b8d4289edac4cc3a23da3d1d2f45ec4d54f Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 10:16:31 +0100 Subject: [PATCH 281/281] use wip instead --- pkgs/pool/CHANGELOG.md | 2 +- pkgs/pool/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pool/CHANGELOG.md b/pkgs/pool/CHANGELOG.md index e9f37916b..56424fc6f 100644 --- a/pkgs/pool/CHANGELOG.md +++ b/pkgs/pool/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.0 +## 1.5.2-wip * Require Dart 3.4. * Move to `dart-lang/tools` monorepo. diff --git a/pkgs/pool/pubspec.yaml b/pkgs/pool/pubspec.yaml index 7e6271226..a205b7494 100644 --- a/pkgs/pool/pubspec.yaml +++ b/pkgs/pool/pubspec.yaml @@ -1,5 +1,5 @@ name: pool -version: 2.0.0 +version: 1.5.2-wip description: >- Manage a finite pool of resources. Useful for controlling concurrent file system or network requests.