process_runner 4.0.0-nullsafety.5 copy "process_runner: ^4.0.0-nullsafety.5" to clipboard
process_runner: ^4.0.0-nullsafety.5 copied to clipboard

outdated

A process invocation astraction for Dart that manages a multiprocess queue.

example/main.dart

// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This example shows how to send a bunch of jobs to ProcessPool for processing.
//
// This example program is actually pretty useful even if you don't use
// process_runner for your Dart project. It can speed up processing of a bunch
// of single-threaded CPU-intensive commands by a multple of the number of
// processor cores you have (modulo being disk/network bound, of course).

// @dart = 2.10

import 'dart:io';

import 'package:process_runner/process_runner.dart';

// This only works for escaped spaces and things in double or single quotes.
// This is just an example, modify to meet your own requirements.
List<String> splitIntoArgs(String args) {
  bool inQuote = false;
  bool inEscape = false;
  String quoteMatch = '';
  final List<String> result = <String>[];
  final List<String> currentArg = <String>[];
  for (int i = 0; i < args.length; ++i) {
    final String char = args[i];
    if (inEscape) {
      switch (char) {
        case 'n':
          currentArg.add('\n');
          break;
        case 't':
          currentArg.add('\t');
          break;
        case 'r':
          currentArg.add('\r');
          break;
        case 'b':
          currentArg.add('\b');
          break;
        default:
          currentArg.add(char);
          break;
      }
      inEscape = false;
      continue;
    }
    if (char == ' ' && !inQuote) {
      result.add(currentArg.join(''));
      currentArg.clear();
      continue;
    }
    if (char == r'\') {
      inEscape = true;
      continue;
    }
    if (inQuote) {
      if (char == quoteMatch) {
        inQuote = false;
        quoteMatch = '';
      } else {
        currentArg.add(char);
      }
      continue;
    }
    if (char == '"' || char == '"') {
      inQuote = !inQuote;
      quoteMatch = args[i];
      continue;
    }
    currentArg.add(char);
  }
  if (currentArg.isNotEmpty) {
    result.add(currentArg.join(''));
  }
  return result;
}

String usage() {
  return '''
main.dart [flags]
    --[no-]help           Print help.
    --[no-]report         Print progress on the jobs while running.
-w, --workers             Specify the number of workers jobs to run simultanously. Defaults to the number of processors on the machine.
-d, --workingDirectory    Specify the working directory to run on
                          (defaults to ".")
-c, --cmd                 Specify a command to add to the commands to be run. Entire command must be quoted by the shell. Commands specified with this option run before those specified with --cmdFile
-f, --file                Specify the name of a file to read commands from, one per line, as they would appear on the command line, with spaces escaped or quoted. Specify "-" to read from stdin.
                          (defaults to "-")
''';
}

String? findOption(String option, List<String> args) {
  for (int i = 0; i < args.length - 1; ++i) {
    if (args[i] == option) {
      return args[i + 1];
    }
  }
  return null;
}

Iterable<String> findAllOptions(String option, List<String> args) sync* {
  for (int i = 0; i < args.length - 1; ++i) {
    if (args[i] == option) {
      yield args[i + 1];
    }
  }
}

Future<void> main(List<String> args) async {
  // Parse args without ArgParser until ArgParser is null-safe.
  if (args.contains('--help')) {
    print('main.dart [flags]');
    print(usage());
    exit(0);
  }

  final bool printReport = args.contains('--report');
  // If the numWorkers is set to null, then the ProcessPool will automatically
  // select the number of processes based on how many CPU cores the machine has.
  final int? numWorkers = int.tryParse(findOption('workers', args) ?? '');
  final Directory workingDirectory = Directory(findOption('workingDirectory', args) ?? '.');
  final List<String> cmds = findAllOptions('cmd', args).toList();

  // Collect the commands to be run from the command file.
  final String commandFile = findOption('file', args) ?? '-';
  List<String> fileCommands = <String>[];
  // Read from stdin if the --file option is set to '-'.
  if (commandFile == '-') {
    String? line = stdin.readLineSync();
    while (line != null) {
      fileCommands.add(line);
      line = stdin.readLineSync();
    }
  } else {
    // Read the commands from a file.
    final File cmdFile = File(commandFile);
    if (!cmdFile.existsSync()) {
      print('Command file "$commandFile" doesn\'t exist.');
      exit(1);
    }
    fileCommands = cmdFile.readAsLinesSync();
  }

  // Collect all the commands, both from the input file, and from the command
  // line. The command line commands come first (although they could all be
  // executed simultaneously, depending on the number of workers, and number of
  // commands).
  final List<String> commands = <String>[
    ...cmds,
    ...fileCommands,
  ];

  // Split each command entry into a list of strings, taking into account some
  // simple quoting and escaping.
  final List<List<String>> splitCommands = commands.map<List<String>>(splitIntoArgs).toList();

  final ProcessPool pool = ProcessPool(
    numWorkers: numWorkers,
    printReport: printReport ? ProcessPool.defaultPrintReport : null,
  );
  final List<WorkerJob> jobs = splitCommands.map<WorkerJob>((List<String> command) {
    return WorkerJob(command, workingDirectory: workingDirectory);
  }).toList();
  await for (final WorkerJob done in pool.startWorkers(jobs)) {
    if (printReport) {
      print('\nFinished job ${done.name}');
    }
    stdout.write(done.result!.stdout);
  }
}
21
likes
0
pub points
98%
popularity

Publisher

unverified uploader

A process invocation astraction for Dart that manages a multiprocess queue.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

async, file, meta, path, platform, process

More

Packages that depend on process_runner