run method

  1. @override
void run()
override

Runs this command.

The return value is wrapped in a Future if necessary and returned by CommandRunner.runCommand.

Implementation

@override
void run() async {
  showUsage(argResults!.rest.isEmpty, () => printUsage());

  final String url = argResults!.rest[0];

  // final Aria2Adapter aria2Adapter = Aria2Adapter();
  // final CurlAdapter curlAdapter = CurlAdapter();
  // final WgetAdapter wgetAdapter = WgetAdapter();
  final DioAdapter dioAdapter = DioAdapter();

  late final DloaderAdapter adapter;

  adapter = dioAdapter;

  // if (aria2Adapter.isAvailable) {
  //   adapter = aria2Adapter;
  // } else if (curlAdapter.isAvailable) {
  //   adapter = curlAdapter;
  // } else if (wgetAdapter.isAvailable) {
  //   adapter = wgetAdapter;
  // } else {
  //   adapter = dioAdapter;
  // }
  Logger.info("Using ${adapter.executable.cmd} adapter");

  final downloader = Dloader(adapter);

  Uri uri = Uri.parse(url);
  // if no filename in url, generate one randomly
  String fileName;
  if (argResults!['name'] != null) {
    fileName = argResults!['name'];
  } else if (uri.pathSegments.isNotEmpty) {
    fileName = uri.pathSegments.last;
  } else {
    fileName = 'file-${DateTime.now().millisecondsSinceEpoch}';
  }
  Logger.info("File name: $fileName");

  File destination;
  if (argResults!["out"] != null) {
    destination = File(argResults!["out"]);
    fileName = destination.path.split("/").last;
  } else {
    Directory tempDir = await XPM.temp('downloads');
    destination = File(join(tempDir.path, fileName));
  }
  Logger.info("Destination: ${destination.path}");

  final progressBarEnabled = !argResults!["no-progress"];

  final ProgressState? progressBar;
  if (progressBarEnabled) {
    progressBar = Progress.withTheme(
      theme: Theme.colorfulTheme,
      length: 100,
      rightPrompt: (current) => ' ${current.toString().padLeft(3)}%',
      leftPrompt: (c) => 'Downloading $fileName ',
    ).interact();
  } else {
    progressBar = null;
  }

  int actualProgress = 0;
  int lastProgress = 0;
  File file = await downloader.download(
    url: url,
    destination: destination,
    userAgent: argResults!['user-agent'],
    disableUserAgent: argResults!['no-user-agent'],
    onProgress: (progress) {
      actualProgress = int.parse(progress['percentComplete']);
      if (progressBarEnabled && actualProgress > 0 && actualProgress > lastProgress) {
        progressBar!.increase(actualProgress - lastProgress);
        lastProgress = actualProgress;
      }
    },
  );

  if (progressBarEnabled) {
    progressBar!.done();
  }

  if (argResults!['md5'] != null ||
      argResults!['sha1'] != null ||
      argResults!['sha256'] != null ||
      argResults!['sha512'] != null ||
      argResults!['sha224'] != null ||
      argResults!['sha384'] != null ||
      argResults!['sha512-224'] != null ||
      argResults!['sha512-256'] != null) {
    Logger.info("Checking hash...");

    String? expectedHash;
    Digest? fileHash;
    final Uint8List asBytes = await file.readAsBytes();

    if (argResults!['sha1'] != null) {
      expectedHash = argResults!['sha1'];
      fileHash = sha1.convert(asBytes);
    } else if (argResults!['sha256'] != null) {
      expectedHash = argResults!['sha256'];
      fileHash = sha256.convert(asBytes);
    } else if (argResults!['sha512'] != null) {
      expectedHash = argResults!['sha512'];
      fileHash = sha512.convert(asBytes);
    } else if (argResults!['md5'] != null) {
      expectedHash = argResults!['md5'];
      fileHash = md5.convert(asBytes);
    } else if (argResults!['sha224'] != null) {
      expectedHash = argResults!['sha224'];
      fileHash = sha224.convert(asBytes);
    } else if (argResults!['sha384'] != null) {
      expectedHash = argResults!['sha384'];
      fileHash = sha384.convert(asBytes);
    } else if (argResults!['sha512-224'] != null) {
      expectedHash = argResults!['sha512-224'];
      fileHash = sha512224.convert(asBytes);
    } else if (argResults!['sha512-256'] != null) {
      expectedHash = argResults!['sha512-256'];
      fileHash = sha512256.convert(asBytes);
    }

    if (fileHash != null && fileHash.toString() != expectedHash) {
      throw Exception('Hash expected $expectedHash, but got $fileHash');
    }
  }

  if (argResults!['bin'] == true || argResults!['exec'] == true) {
    final runner = Run();

    if (argResults!['exec'] == true && !Platform.isWindows) {
      bool asExec = await runner.asExec(file.path, sudo: await Executable('sudo').exists());
      if (asExec) {
        Logger.info('Made $file executable');
      } else {
        throw Exception('Failed to make $file executable');
      }
    }

    if (argResults!['bin'] == true) {
      // @FIXME shouldn't $destination be set instead use this logic?
      final File? toBin = await moveToBin(file, runner: runner, sudo: await Executable('sudo').exists());

      if (toBin != null) {
        Logger.info('Installed $file to bin folder: ${toBin.path}');
        file = toBin;
      } else {
        throw Exception('Failed to install $file to bin folder');
      }
    }
  }

  print(file.absolute.path);
  exit(success);
}