Drop chainToCompleter util (#2371)

A Completer can be completed with a `Future` which matches the behavior
here, except in the case where we intentionally call `complete` late
because we may complete with a value or error in a different code path.
In this case we only ever complete with a value from one place.

Refactor to `async/await` in  `_authorize`.
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart
index ad777a6..6095640 100644
--- a/lib/src/oauth2.dart
+++ b/lib/src/oauth2.dart
@@ -180,7 +180,7 @@
 /// Gets the user to authorize pub as a client of pub.dartlang.org via oauth2.
 ///
 /// Returns a Future that completes to a fully-authorized [Client].
-Future<Client> _authorize() {
+Future<Client> _authorize() async {
   var grant =
       AuthorizationCodeGrant(_identifier, _authorizationEndpoint, tokenEndpoint,
           secret: _secret,
@@ -192,38 +192,35 @@
   // Google OAuth2 server via redirect. This server will close itself as soon as
   // the code is received.
   var completer = Completer();
-  bindServer('localhost', 0).then((server) {
-    shelf_io.serveRequests(server, (request) {
-      if (request.url.path.isNotEmpty) {
-        return shelf.Response.notFound('Invalid URI.');
-      }
+  var server = await bindServer('localhost', 0);
+  shelf_io.serveRequests(server, (request) {
+    if (request.url.path.isNotEmpty) {
+      return shelf.Response.notFound('Invalid URI.');
+    }
 
-      log.message('Authorization received, processing...');
-      var queryString = request.url.query ?? '';
+    log.message('Authorization received, processing...');
+    var queryString = request.url.query ?? '';
 
-      // Closing the server here is safe, since it will wait until the response
-      // is sent to actually shut down.
-      server.close();
-      chainToCompleter(
-          grant.handleAuthorizationResponse(queryToMap(queryString)),
-          completer);
+    // Closing the server here is safe, since it will wait until the response
+    // is sent to actually shut down.
+    server.close();
+    completer
+        .complete(grant.handleAuthorizationResponse(queryToMap(queryString)));
 
-      return shelf.Response.found('https://pub.dartlang.org/authorized');
-    });
-
-    var authUrl = grant.getAuthorizationUrl(
-        Uri.parse('http://localhost:${server.port}'),
-        scopes: _scopes);
-
-    log.message(
-        'Pub needs your authorization to upload packages on your behalf.\n'
-        'In a web browser, go to $authUrl\n'
-        'Then click "Allow access".\n\n'
-        'Waiting for your authorization...');
+    return shelf.Response.found('https://pub.dartlang.org/authorized');
   });
 
-  return completer.future.then((client) {
-    log.message('Successfully authorized.\n');
-    return client;
-  });
+  var authUrl = grant.getAuthorizationUrl(
+      Uri.parse('http://localhost:${server.port}'),
+      scopes: _scopes);
+
+  log.message(
+      'Pub needs your authorization to upload packages on your behalf.\n'
+      'In a web browser, go to $authUrl\n'
+      'Then click "Allow access".\n\n'
+      'Waiting for your authorization...');
+
+  var client = await completer.future;
+  log.message('Successfully authorized.\n');
+  return client;
 }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 2466dde..2897db7 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -354,12 +354,6 @@
 String sha1(String source) =>
     crypto.sha1.convert(utf8.encode(source)).toString();
 
-/// Configures [future] so that its result (success or exception) is passed on
-/// to [completer].
-void chainToCompleter(Future future, Completer completer) {
-  future.then(completer.complete, onError: completer.completeError);
-}
-
 /// A regular expression matching a trailing CR character.
 final _trailingCR = RegExp(r'\r$');