| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 import 'dart:async'; | 5 import '../lib/src/command_runner.dart'; | 
| 6 import 'dart:io'; |  | 
| 7 |  | 
| 8 import 'package:args/args.dart'; |  | 
| 9 import 'package:http/http.dart' as http; |  | 
| 10 import 'package:path/path.dart' as path; |  | 
| 11 import 'package:stack_trace/stack_trace.dart'; |  | 
| 12 |  | 
| 13 import '../lib/src/command.dart'; |  | 
| 14 import '../lib/src/exceptions.dart'; |  | 
| 15 import '../lib/src/exit_codes.dart' as exit_codes; |  | 
| 16 import '../lib/src/http.dart'; |  | 
| 17 import '../lib/src/io.dart'; |  | 
| 18 import '../lib/src/log.dart' as log; |  | 
| 19 import '../lib/src/sdk.dart' as sdk; |  | 
| 20 import '../lib/src/solver/version_solver.dart'; |  | 
| 21 import '../lib/src/utils.dart'; |  | 
| 22 | 6 | 
| 23 void main(List<String> arguments) { | 7 void main(List<String> arguments) { | 
| 24   ArgResults options; | 8   new PubCommandRunner().run(arguments); | 
| 25 |  | 
| 26   try { |  | 
| 27     options = PubCommand.pubArgParser.parse(arguments); |  | 
| 28   } on FormatException catch (e) { |  | 
| 29     log.error(e.message); |  | 
| 30     log.error('Run "pub help" to see available options.'); |  | 
| 31     flushThenExit(exit_codes.USAGE); |  | 
| 32     return; |  | 
| 33   } |  | 
| 34 |  | 
| 35   log.withPrejudice = options['with-prejudice']; |  | 
| 36 |  | 
| 37   if (options['version']) { |  | 
| 38     log.message('Pub ${sdk.version}'); |  | 
| 39     return; |  | 
| 40   } |  | 
| 41 |  | 
| 42   if (options['help']) { |  | 
| 43     PubCommand.printGlobalUsage(); |  | 
| 44     return; |  | 
| 45   } |  | 
| 46 |  | 
| 47   if (options['trace']) { |  | 
| 48     log.recordTranscript(); |  | 
| 49   } |  | 
| 50 |  | 
| 51   switch (options['verbosity']) { |  | 
| 52     case 'normal': log.verbosity = log.Verbosity.NORMAL; break; |  | 
| 53     case 'io':     log.verbosity = log.Verbosity.IO; break; |  | 
| 54     case 'solver': log.verbosity = log.Verbosity.SOLVER; break; |  | 
| 55     case 'all':    log.verbosity = log.Verbosity.ALL; break; |  | 
| 56     default: |  | 
| 57       // No specific verbosity given, so check for the shortcut. |  | 
| 58       if (options['verbose']) { |  | 
| 59         log.verbosity = log.Verbosity.ALL; |  | 
| 60       } |  | 
| 61       break; |  | 
| 62   } |  | 
| 63 |  | 
| 64   log.fine('Pub ${sdk.version}'); |  | 
| 65 |  | 
| 66   var cacheDir; |  | 
| 67   if (Platform.environment.containsKey('PUB_CACHE')) { |  | 
| 68     cacheDir = Platform.environment['PUB_CACHE']; |  | 
| 69   } else if (Platform.operatingSystem == 'windows') { |  | 
| 70     var appData = Platform.environment['APPDATA']; |  | 
| 71     cacheDir = path.join(appData, 'Pub', 'Cache'); |  | 
| 72   } else { |  | 
| 73     cacheDir = '${Platform.environment['HOME']}/.pub-cache'; |  | 
| 74   } |  | 
| 75 |  | 
| 76   validatePlatform().then((_) => runPub(cacheDir, options, arguments)); |  | 
| 77 } | 9 } | 
| 78 |  | 
| 79 /// Runs the appropriate pub command whose [arguments] have been parsed to |  | 
| 80 /// [options] using the system cache in [cacheDir]. |  | 
| 81 /// |  | 
| 82 /// Handles and correctly reports any errors that occur while running. |  | 
| 83 void runPub(String cacheDir, ArgResults options, List<String> arguments) { |  | 
| 84   var captureStackChains = |  | 
| 85       options['trace'] || |  | 
| 86       options['verbose'] || |  | 
| 87       options['verbosity'] == 'all'; |  | 
| 88 |  | 
| 89   captureErrors(() => invokeCommand(cacheDir, options), |  | 
| 90       captureStackChains: captureStackChains).catchError((error, Chain chain) { |  | 
| 91     log.exception(error, chain); |  | 
| 92 |  | 
| 93     if (options['trace']) { |  | 
| 94       log.dumpTranscript(); |  | 
| 95     } else if (!isUserFacingException(error)) { |  | 
| 96       log.error(""" |  | 
| 97 This is an unexpected error. Please run |  | 
| 98 |  | 
| 99     pub --trace ${arguments.map((arg) => "'$arg'").join(' ')} |  | 
| 100 |  | 
| 101 and include the results in a bug report on http://dartbug.com/new. |  | 
| 102 """); |  | 
| 103     } |  | 
| 104 |  | 
| 105     return flushThenExit(chooseExitCode(error)); |  | 
| 106   }).then((_) { |  | 
| 107     // Explicitly exit on success to ensure that any dangling dart:io handles |  | 
| 108     // don't cause the process to never terminate. |  | 
| 109     return flushThenExit(exit_codes.SUCCESS); |  | 
| 110   }); |  | 
| 111 } |  | 
| 112 |  | 
| 113 /// Returns the appropriate exit code for [exception], falling back on 1 if no |  | 
| 114 /// appropriate exit code could be found. |  | 
| 115 int chooseExitCode(exception) { |  | 
| 116   while (exception is WrappedException) exception = exception.innerError; |  | 
| 117 |  | 
| 118   if (exception is HttpException || exception is http.ClientException || |  | 
| 119       exception is SocketException || exception is PubHttpException || |  | 
| 120       exception is DependencyNotFoundException) { |  | 
| 121     return exit_codes.UNAVAILABLE; |  | 
| 122   } else if (exception is FormatException || exception is DataException) { |  | 
| 123     return exit_codes.DATA; |  | 
| 124   } else if (exception is UsageException) { |  | 
| 125     return exit_codes.USAGE; |  | 
| 126   } else { |  | 
| 127     return 1; |  | 
| 128   } |  | 
| 129 } |  | 
| 130 |  | 
| 131 /// Walks the command tree and runs the selected pub command. |  | 
| 132 Future invokeCommand(String cacheDir, ArgResults mainOptions) async { |  | 
| 133   var commands = PubCommand.mainCommands; |  | 
| 134   var command; |  | 
| 135   var commandString = "pub"; |  | 
| 136   var options = mainOptions; |  | 
| 137 |  | 
| 138   while (commands.isNotEmpty) { |  | 
| 139     if (options.command == null) { |  | 
| 140       if (options.rest.isEmpty) { |  | 
| 141         if (command == null) { |  | 
| 142           // No top-level command was chosen. |  | 
| 143           PubCommand.printGlobalUsage(); |  | 
| 144           return new Future.value(); |  | 
| 145         } |  | 
| 146 |  | 
| 147         command.usageError('Missing subcommand for "$commandString".'); |  | 
| 148       } else { |  | 
| 149         if (command == null) { |  | 
| 150           PubCommand.usageErrorWithCommands(commands, |  | 
| 151               'Could not find a command named "${options.rest[0]}".'); |  | 
| 152         } |  | 
| 153 |  | 
| 154         command.usageError('Could not find a subcommand named ' |  | 
| 155             '"${options.rest[0]}" for "$commandString".'); |  | 
| 156       } |  | 
| 157     } |  | 
| 158 |  | 
| 159     // Step into the command. |  | 
| 160     options = options.command; |  | 
| 161     command = commands[options.name]; |  | 
| 162     commands = command.subcommands; |  | 
| 163     commandString += " ${options.name}"; |  | 
| 164 |  | 
| 165     if (options['help']) { |  | 
| 166       command.printUsage(); |  | 
| 167       return new Future.value(); |  | 
| 168     } |  | 
| 169   } |  | 
| 170 |  | 
| 171   // Make sure there aren't unexpected arguments. |  | 
| 172   if (!command.takesArguments && options.rest.isNotEmpty) { |  | 
| 173     command.usageError( |  | 
| 174         'Command "${options.name}" does not take any arguments.'); |  | 
| 175   } |  | 
| 176 |  | 
| 177   try { |  | 
| 178     // TODO(rnystrom): Use await here when this is fixed: |  | 
| 179     // https://github.com/dart-lang/async_await/issues/40. |  | 
| 180     return command.run(cacheDir, mainOptions, options); |  | 
| 181   } finally { |  | 
| 182     command.cache.deleteTempDir(); |  | 
| 183   } |  | 
| 184 } |  | 
| 185 |  | 
| 186 /// Checks that pub is running on a supported platform. |  | 
| 187 /// |  | 
| 188 /// If it isn't, it prints an error message and exits. Completes when the |  | 
| 189 /// validation is done. |  | 
| 190 Future validatePlatform() async { |  | 
| 191   if (Platform.operatingSystem != 'windows') return; |  | 
| 192 |  | 
| 193   var result = await runProcess('ver', []); |  | 
| 194   if (result.stdout.join('\n').contains('XP')) { |  | 
| 195     log.error('Sorry, but pub is not supported on Windows XP.'); |  | 
| 196     await flushThenExit(exit_codes.USAGE); |  | 
| 197   } |  | 
| 198 } |  | 
| OLD | NEW | 
|---|