<commit_before>import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:mirrors';

import 'package:args/args.dart';
import 'package:path/path.dart' as path_lib;
import 'package:yaml/yaml.dart';
import 'package:pub_semver/pub_semver.dart';

import '../utilities/source_generator.dart';
import 'auth.dart';
import 'create.dart';
import 'db.dart';
import 'document.dart';
import 'serve.dart';
import 'setup.dart';

export 'auth.dart';
export 'create.dart';
export 'db.dart';
export 'document.dart';
export 'serve.dart';
export 'setup.dart';

/// Exceptions thrown by command line interfaces.
class CLIException {
  CLIException(this.message, {this.instructions});

  List<String> instructions;
  String message;

  String toString() => message;
}

enum CLIColor { red, green, blue, boldRed, boldGreen, boldBlue, boldNone, none }

abstract class CLIResultHandler {
  ArgResults values;
}

/// A command line interface command.
abstract class CLICommand implements CLIResultHandler {
  static const _Delimiter = "-- ";
  static const _Tabs = "    ";
  static const _ErrorDelimiter = "*** ";

  /// Options for this command.
  ArgParser options = new ArgParser(allowTrailingOptions: true)
    ..addOption("directory",
        abbr: "d",
        help: "Project directory to execute command in",
        defaultsTo: Directory.current.path)
    ..addFlag("help", abbr: "h", help: "Shows this", negatable: false)
    ..addFlag("stacktrace",
        help: "Shows the stacktrace if an error occurs", defaultsTo: false)
    ..addFlag("color",
        help: "Toggles ANSI color", negatable: true, defaultsTo: true);

  ArgResults values;
  bool get showColors => values["color"];
  bool get helpMeItsScary => values["help"];
  bool get showStacktrace => values["stacktrace"];
  Map<String, CLICommand> _commandMap = {};

  StringSink _outputSink = stdout;
  StringSink get outputSink => _outputSink;
  void set outputSink(StringSink sink) {
    _outputSink = sink;
    _commandMap.values.forEach((cmd) {
      cmd.outputSink = sink;
    });
  }

  Version get toolVersion => _toolVersion;
  Version _toolVersion;

  void registerCommand(CLICommand cmd) {
    _commandMap[cmd.name] = cmd;
    options.addCommand(cmd.name, cmd.options);
  }

  /// Handles the command input.
  ///
  /// Override this method to perform actions for this command.
  ///
  /// Return value is the value returned to the command line operation. Return 0 for success.
  Future<int> handle();

  /// Cleans up any resources used during this command.
  ///
  /// Delete temporary files or close down any [Stream]s.
  Future cleanup() async {}

  /// Invoked on this instance when this command is executed from the command line.
  ///
  /// Do not override this method. This method invokes [handle] within a try-catch block
  /// and will invoke [cleanup] when complete.
  Future<int> process(ArgResults results,
      {List<String> parentCommandNames}) async {
    if (results.command != null) {
      if (parentCommandNames == null) {
        parentCommandNames = [name];
      } else {
        parentCommandNames.add(name);
      }
      return _commandMap[results.command.name]
          .process(results.command, parentCommandNames: parentCommandNames);
    }

    try {
      values = results;

      await determineToolVersion();

      displayInfo("Aqueduct CLI Version: ${toolVersion}");
      preProcess();

      if (helpMeItsScary) {
        printHelp(parentCommandName: parentCommandNames?.join(" "));
        return 0;
      }

      return await handle();
    } on CLIException catch (e, st) {
      displayError(e.message);
      e.instructions?.forEach((instruction) {
        displayProgress(instruction);
      });
      print("");
      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } on IsolateExecutorException catch (e, st) {
      displayError(e.message);
      displayProgress("Try running 'pub get' first.");
      print("");

      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } catch (e, st) {
      displayError("$e");
      print("");
      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } finally {
      await cleanup();
    }
    return 1;
  }

  Future determineToolVersion() async {
    try {
      var toolLibraryFilePath = (await Isolate.resolvePackageUri(currentMirrorSystem().findLibrary(#aqueduct).uri)).path;
      var idx = toolLibraryFilePath.lastIndexOf("aqueduct${path_lib.separator}lib");
      toolLibraryFilePath = toolLibraryFilePath.substring(0, idx + "aqueduct".length);

      var toolLibraryDirectory = new Directory(toolLibraryFilePath);
      var toolPubspecFile = new File.fromUri(toolLibraryDirectory.absolute.uri.resolve("pubspec.yaml"));
      Map<String, dynamic> toolPubspecContents = loadYaml(toolPubspecFile.readAsStringSync());
      String toolVersion = toolPubspecContents["version"];
      _toolVersion = new Version.parse(toolVersion);
    } catch (_) {}
  }

  void preProcess() {

  }

  void displayError(String errorMessage,
      {bool showUsage: false, CLIColor color: CLIColor.boldRed}) {
    outputSink.writeln(
        "${colorSymbol(color)}${_ErrorDelimiter}$errorMessage$defaultColorSymbol");
    if (showUsage) {
      outputSink.writeln("\n${options.usage}");
    }
  }

  void displayInfo(String infoMessage, {CLIColor color: CLIColor.boldNone}) {
    outputSink.writeln("${colorSymbol(color)}${_Delimiter}$infoMessage$defaultColorSymbol");
  }

  void displayProgress(String progressMessage,
      {CLIColor color: CLIColor.none}) {
    outputSink.writeln("${colorSymbol(color)}${_Tabs}$progressMessage$defaultColorSymbol");
  }

  String colorSymbol(CLIColor color) {
    if (!showColors) {
      return "";
    }
    return _lookupTable[color];
  }
<commit_msg>Fix CLI version resolution (#244)<commit_after>import 'dart:async';
import 'dart:io';
import 'dart:isolate';
import 'dart:mirrors';

import 'package:args/args.dart';
import 'package:path/path.dart' as path_lib;
import 'package:yaml/yaml.dart';
import 'package:pub_semver/pub_semver.dart';

import '../utilities/source_generator.dart';
import 'auth.dart';
import 'create.dart';
import 'db.dart';
import 'document.dart';
import 'serve.dart';
import 'setup.dart';

export 'auth.dart';
export 'create.dart';
export 'db.dart';
export 'document.dart';
export 'serve.dart';
export 'setup.dart';

/// Exceptions thrown by command line interfaces.
class CLIException {
  CLIException(this.message, {this.instructions});

  List<String> instructions;
  String message;

  String toString() => message;
}

enum CLIColor { red, green, blue, boldRed, boldGreen, boldBlue, boldNone, none }

abstract class CLIResultHandler {
  ArgResults values;
}

/// A command line interface command.
abstract class CLICommand implements CLIResultHandler {
  static const _Delimiter = "-- ";
  static const _Tabs = "    ";
  static const _ErrorDelimiter = "*** ";

  /// Options for this command.
  ArgParser options = new ArgParser(allowTrailingOptions: true)
    ..addOption("directory",
        abbr: "d",
        help: "Project directory to execute command in",
        defaultsTo: Directory.current.path)
    ..addFlag("help", abbr: "h", help: "Shows this", negatable: false)
    ..addFlag("stacktrace",
        help: "Shows the stacktrace if an error occurs", defaultsTo: false)
    ..addFlag("color",
        help: "Toggles ANSI color", negatable: true, defaultsTo: true);

  ArgResults values;
  bool get showColors => values["color"];
  bool get helpMeItsScary => values["help"];
  bool get showStacktrace => values["stacktrace"];
  Map<String, CLICommand> _commandMap = {};

  StringSink _outputSink = stdout;
  StringSink get outputSink => _outputSink;
  void set outputSink(StringSink sink) {
    _outputSink = sink;
    _commandMap.values.forEach((cmd) {
      cmd.outputSink = sink;
    });
  }

  Version get toolVersion => _toolVersion;
  Version _toolVersion;

  void registerCommand(CLICommand cmd) {
    _commandMap[cmd.name] = cmd;
    options.addCommand(cmd.name, cmd.options);
  }

  /// Handles the command input.
  ///
  /// Override this method to perform actions for this command.
  ///
  /// Return value is the value returned to the command line operation. Return 0 for success.
  Future<int> handle();

  /// Cleans up any resources used during this command.
  ///
  /// Delete temporary files or close down any [Stream]s.
  Future cleanup() async {}

  /// Invoked on this instance when this command is executed from the command line.
  ///
  /// Do not override this method. This method invokes [handle] within a try-catch block
  /// and will invoke [cleanup] when complete.
  Future<int> process(ArgResults results,
      {List<String> parentCommandNames}) async {
    if (results.command != null) {
      if (parentCommandNames == null) {
        parentCommandNames = [name];
      } else {
        parentCommandNames.add(name);
      }
      return _commandMap[results.command.name]
          .process(results.command, parentCommandNames: parentCommandNames);
    }

    try {
      values = results;

      await determineToolVersion();

      displayInfo("Aqueduct CLI Version: ${toolVersion}");
      preProcess();

      if (helpMeItsScary) {
        printHelp(parentCommandName: parentCommandNames?.join(" "));
        return 0;
      }

      return await handle();
    } on CLIException catch (e, st) {
      displayError(e.message);
      e.instructions?.forEach((instruction) {
        displayProgress(instruction);
      });
      print("");
      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } on IsolateExecutorException catch (e, st) {
      displayError(e.message);
      displayProgress("Try running 'pub get' first.");
      print("");

      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } catch (e, st) {
      displayError("$e");
      print("");
      if (showStacktrace) {
        displayError("Offending Stacktrace ***", color: CLIColor.red);
        print("$st");
      }
    } finally {
      await cleanup();
    }
    return 1;
  }

  Future determineToolVersion() async {
    try {
      var toolLibraryFilePath = (await Isolate.resolvePackageUri(currentMirrorSystem().findLibrary(#aqueduct).uri))
          .toFilePath(windows: Platform.isWindows);
      var aqueductDirectory = new Directory(FileSystemEntity.parentOf(FileSystemEntity.parentOf(toolLibraryFilePath)));
      var toolPubspecFile = new File.fromUri(aqueductDirectory.absolute.uri.resolve("pubspec.yaml"));

      Map<String, dynamic> toolPubspecContents = loadYaml(toolPubspecFile.readAsStringSync());
      String toolVersion = toolPubspecContents["version"];
      _toolVersion = new Version.parse(toolVersion);
    } catch (e) {
      print(e);
    }
  }

  void preProcess() {

  }

  void displayError(String errorMessage,
      {bool showUsage: false, CLIColor color: CLIColor.boldRed}) {
    outputSink.writeln(
        "${colorSymbol(color)}${_ErrorDelimiter}$errorMessage$defaultColorSymbol");
    if (showUsage) {
      outputSink.writeln("\n${options.usage}");
    }
  }

  void displayInfo(String infoMessage, {CLIColor color: CLIColor.boldNone}) {
    outputSink.writeln("${colorSymbol(color)}${_Delimiter}$infoMessage$defaultColorSymbol");
  }

  void displayProgress(String progressMessage,
      {CLIColor color: CLIColor.none}) {
    outputSink.writeln("${colorSymbol(color)}${_Tabs}$progressMessage$defaultColorSymbol");
  }

  String colorSymbol(CLIColor color) {
    if (!showColors) {
      return "";
    }
    return _lookupTable[color];
  }

{'fraction_non_alphanumeric': 0.1288993525603296, 'fraction_numerical': 0.0008408307407718826, 'mean_word_length': 3.4446935724962633, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3189785', 'n_tokens_mistral': 3549, 'n_tokens_neox': 3520, 'n_words': 871}