Chromium Code Reviews| Index: utils/pub/command_lish.dart |
| diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart |
| index f775b46c58860c778f8b0a55e4a1b65bdf48c0f8..a96f55060bcc9eeac9a30a99d7db99691751479b 100644 |
| --- a/utils/pub/command_lish.dart |
| +++ b/utils/pub/command_lish.dart |
| @@ -10,6 +10,7 @@ import 'dart:uri'; |
| import '../../pkg/args/lib/args.dart'; |
| import '../../pkg/http/lib/http.dart' as http; |
| +import 'directory_tree.dart'; |
| import 'git.dart' as git; |
| import 'io.dart'; |
| import 'log.dart' as log; |
| @@ -33,21 +34,12 @@ class LishCommand extends PubCommand { |
| /// The URL of the server to which to upload the package. |
| Uri get server => new Uri.fromString(commandOptions['server']); |
| - Future onRun() { |
| + Future _publish(packageBytes) { |
| var cloudStorageUrl; |
| return oauth2.withClient(cache, (client) { |
| // TODO(nweiz): Cloud Storage can provide an XML-formatted error. We |
| // should report that error and exit. |
| - return Futures.wait([ |
| - client.get(server.resolve("/packages/versions/new.json")), |
| - _filesToPublish.transform((files) { |
| - log.fine('Archiving and publishing ${entrypoint.root}.'); |
| - return createTarGz(files, baseDir: entrypoint.root.dir); |
| - }).chain(consumeInputStream), |
| - _validate() |
| - ]).chain((results) { |
| - var response = results[0]; |
| - var packageBytes = results[1]; |
| + return client.get(server.resolve("/packages/versions/new.json")).chain((response) { |
|
nweiz
2012/12/12 21:21:21
Long line
Bob Nystrom
2012/12/12 21:45:36
Done.
|
| var parameters = _parseJson(response); |
| var url = _expectField(parameters, 'url', response); |
| @@ -98,21 +90,40 @@ class LishCommand extends PubCommand { |
| } |
| } else if (e is oauth2.ExpirationException) { |
| log.error("Pub's authorization to upload packages has expired and " |
| - "can't be automatically refreshed."); |
| - return onRun(); |
| + "can't be automatically refreshed."); |
| + return _publish(packageBytes); |
| } else if (e is oauth2.AuthorizationException) { |
| var message = "OAuth2 authorization failed"; |
| if (e.description != null) message = "$message (${e.description})"; |
| log.error("$message."); |
| - return oauth2.clearCredentials(cache).chain((_) => onRun()); |
| + return oauth2.clearCredentials(cache).chain((_) => |
| + _publish(packageBytes)); |
| } else { |
| throw e; |
| } |
| }); |
| } |
| + Future onRun() { |
| + var files; |
| + return _filesToPublish.transform((f) { |
| + files = f; |
| + log.fine('Archiving and publishing ${entrypoint.root}.'); |
| + return createTarGz(files, baseDir: entrypoint.root.dir); |
| + }).chain(consumeInputStream).chain((packageBytes) { |
|
nweiz
2012/12/12 21:21:21
Why are we blocking on creating the tarball? Can't
Bob Nystrom
2012/12/12 21:45:36
Yesterday, you mentioned wanting to eventually val
nweiz
2012/12/12 21:59:51
I was thinking we'd just pass the archive future i
|
| + // Show the package contents so the user can verify they look OK. |
| + var package = entrypoint.root; |
| + log.message( |
| + 'Publishing "${package.name}" ${package.version}:\n' |
| + '${generateTree(files)}'); |
| + |
| + // Validate the package. |
| + return _validate().chain((_) => _publish(packageBytes)); |
| + }); |
| + } |
| + |
| /// The basenames of files that are automatically excluded from archives. |
| - final _BLACKLISTED_FILES = const ['pubspec.lock']; |
| + final _BLACKLISTED_FILES = const ['.DS_Store', 'pubspec.lock']; |
|
nweiz
2012/12/12 21:21:21
Adding .DS_Store here is unnecessary; hidden files
Bob Nystrom
2012/12/12 21:45:36
Done.
|
| /// The basenames of directories that are automatically excluded from |
| /// archives. |
| @@ -135,15 +146,21 @@ class LishCommand extends PubCommand { |
| return listDir(rootDir, recursive: true).chain((entries) { |
| return Futures.wait(entries.map((entry) { |
| - return fileExists(entry).transform((isFile) => isFile ? entry : null); |
| + return fileExists(entry).transform((isFile) { |
| + // Skip directories. |
| + if (!isFile) return null; |
| + |
| + // Make it relative to the package root. |
| + return relativeTo(entry, rootDir); |
|
nweiz
2012/12/12 21:21:21
I'm worried that this will cause tricky bugs in th
Bob Nystrom
2012/12/12 21:45:36
Good point. It does work now and I'd like to get t
|
| + }); |
| })); |
| }); |
| }).transform((files) => files.filter((file) { |
| if (file == null || _BLACKLISTED_FILES.contains(basename(file))) { |
| return false; |
| } |
| - return !splitPath(relativeTo(file, rootDir)) |
| - .some(_BLACKLISTED_DIRECTORIES.contains); |
| + |
| + return !splitPath(file).some(_BLACKLISTED_DIRECTORIES.contains); |
| })); |
| } |
| @@ -180,15 +197,22 @@ class LishCommand extends PubCommand { |
| var errors = pair.first; |
| var warnings = pair.last; |
| - if (errors.isEmpty && warnings.isEmpty) return new Future.immediate(null); |
| - if (!errors.isEmpty) throw "Package validation failed."; |
| + if (!errors.isEmpty) { |
| + throw "Sorry, your package is missing " |
| + "${(errors.length > 1) ? 'some requirements' : 'a requirement'} " |
| + "and can't be published yet.\nFor more information, see: " |
| + "http://pub.dartlang.org/doc/pub-lish.html.\n"; |
| + } |
| + |
| + var message = 'Looks great! Are you ready to upload your package'; |
| + |
| + if (!warnings.isEmpty) { |
| + var s = warnings.length == 1 ? '' : 's'; |
| + message = "Package has ${warnings.length} warning$s. Upload anyway"; |
| + } |
| - var s = warnings.length == 1 ? '' : 's'; |
| - stdout.writeString("Package has ${warnings.length} warning$s. Upload " |
| - "anyway (y/n)? "); |
| - return readLine().transform((line) { |
| - if (new RegExp(r"^[yY]").hasMatch(line)) return; |
| - throw "Package upload canceled."; |
| + return confirm(message).transform((confirmed) { |
| + if (!confirmed) throw "Package upload canceled."; |
| }); |
| }); |
| } |