diff --git a/lib/core/app_data_manager.dart b/lib/core/app_data_manager.dart index 1561625..6322983 100644 --- a/lib/core/app_data_manager.dart +++ b/lib/core/app_data_manager.dart @@ -45,8 +45,9 @@ class AppDataManager { Future gitCount() async { var shell = StringBuffer(); shell.writeln('git rev-list --all HEAD --all --count'); + _workspace = '/home/deck/work/dart_framework'; var process = await ProcessExecutor.start(shell, workspace: _workspace); - await process.process.exitCode; + await process.waitForExit(); return dataFutrue(int.parse(process.stdoutArr.last)); } @@ -60,7 +61,7 @@ class AppDataManager { case SCMType.Git: shell.writeln('git rev-list --all HEAD --all --count'); var process = await ProcessExecutor.start(shell, workspace: _workspace); - await process.process.exitCode; + await process.waitForExit(); number = int.parse(process.stdoutArr.last); break; } @@ -107,7 +108,7 @@ class AppDataManager { var shell = StringBuffer(); shell.writeln('git rev-parse HEAD'); var process = await ProcessExecutor.start(shell, workspace: _workspace); - await process.process.exitCode; + await process.waitForExit(); var hash = process.stdoutArr.last; print('#### Git Hash: $hash'); return dataFutrue(hash); diff --git a/lib/platform/process.dart b/lib/platform/process.dart index 671d54a..beaebe1 100644 --- a/lib/platform/process.dart +++ b/lib/platform/process.dart @@ -11,29 +11,30 @@ import 'package:dart_framework/utils/system_util.dart'; typedef LogHandler = Function(String, LogType); class ProcessData { - late Process process; + int? exitCode; + late Process _process; late File file; - late bool isRunning; - late int exitCode; - Function(ProcessData)? _endListener; late StringBuffer stdout; late StringBuffer stderr; final bool _enableStdout; final bool _enableStderr; + final Completer _completer = Completer(); LogHandler? _logHandler; - late Converter, String> _decoder = utf8.decoder; + bool _completeStdout = false; + bool _completeStderr = false; + bool _completeExitCode = false; + late Converter, String> _decoder; // ignore: no_leading_underscores_for_local_identifiers - ProcessData(this._enableStdout, this._enableStderr, {LogHandler? logHandler}) { + ProcessData(this._enableStdout, this._enableStderr, + {LogHandler? logHandler, Converter, String>? decoder}) { _logHandler = logHandler; - } - - Function(ProcessData)? get endListener { - return _endListener; + _decoder = decoder ?? utf8.decoder; } bool get isSuccess { - return ProcessExecutor.getSuccess(exitCode); + if (Platform.isWindows) return exitCode == 1; + return exitCode == 0; } List get stdoutArr { @@ -56,93 +57,97 @@ class ProcessData { return list; } - set decoder(Converter, String> value) { - _decoder = value; + Process get process { + return _process; } - set processValue(Process value) { - process = value; + set process(Process value) { + _process = value; stdout = StringBuffer(); stderr = StringBuffer(); - process.stdout.transform(_decoder).listen((event) { + _process.stdout.transform(_decoder).transform(LineSplitter()).listen( + (event) { stdout.writeln(event); if (_enableStdout) { log(event, LogType.verbose); } + }, onDone: () { + _completeStdout = true; + _checkComplete(); }); - process.stderr.transform(_decoder).listen((event) { + _process.stderr.transform(_decoder).transform(LineSplitter()).listen( + (event) { stderr.writeln(event); if (_enableStderr) { log('[Error] $event', LogType.error); } + }, onDone: () { + _completeStderr = true; + _checkComplete(); }); - isRunning = true; - checkExit(); + _checkExitCode(); } void log(String message, LogType logType) { - if(_logHandler == null) { + if (_logHandler == null) { print(message); } else { _logHandler!(message, logType); } } - void addEndListener(Function(ProcessData) listener) { - _endListener = listener; - } - - void removeEndListener() { - _endListener = null; - } - - void checkExit() async { - exitCode = await process.exitCode; - deleteFile(); - isRunning = false; - if (_endListener != null) _endListener!(this); - } - void terminate() { - process.kill(); + _process.kill(); + _deleteFile(); } - void deleteFile() async { - if (await file.exists()) { - await file.delete(); + void _deleteFile() async { + if (file.existsSync()) { + file.deleteSync(); } } - void dispose() async { - deleteFile(); + void _checkExitCode() async { + exitCode = await _process.exitCode; + _completeExitCode = true; + _checkComplete(); + } + + void _checkComplete() { + if (_completeExitCode && _completeStdout && _completeStderr) { + _completer.complete(); + } } Future waitForExit() async { - await process.exitCode; - return simpleFuture; + return _completer.future; } } class ProcessExecutor { static Future startExe(String exe, List args, - {String? workspace, bool? printStdout, bool? printStderr, LogHandler? logHandler}) async { + {String? workspace, + bool? printStdout, + bool? printStderr, + LogHandler? logHandler}) async { var arg = '$exe ${args.join(' ')}'; var printStdout_ = printStdout ?? true; var printStderr_ = printStderr ?? true; - var processData = ProcessData(printStdout_, printStderr_, logHandler: logHandler); + var processData = + ProcessData(printStdout_, printStderr_, logHandler: logHandler); if (Platform.isMacOS || Platform.isWindows) { workspace = workspace ?? Directory.systemTemp.path; - if(printStdout_) { - logHandler??('Execute Shell: $arg', LogType.verbose); + if (printStdout_) { + logHandler ?? ('Execute Shell: $arg', LogType.verbose); } try { - processData.processValue = + processData.process = await Process.start(exe, args, workingDirectory: workspace); } on Exception catch (e) { - logHandler??(e, LogType.error); + logHandler ?? (e, LogType.error); } } else { - logHandler??('This platform not support process executor.'); + logHandler ?? ('This platform not support process executor.'); } return dataFutrue(processData); } @@ -151,40 +156,47 @@ class ProcessExecutor { {Converter, String>? decoder, String? workspace, bool? printStdout, - bool? printStderr, LogHandler? logHandler}) async { + bool? printStderr, + LogHandler? logHandler}) async { var c = Completer(); try { var printStdout_ = printStdout ?? true; var printStderr_ = printStderr ?? true; - var processData = ProcessData(printStdout_, printStderr_, logHandler: logHandler); - if (decoder != null) { - processData.decoder = decoder; - } + var processData = ProcessData(printStdout_, printStderr_, + logHandler: logHandler, decoder: decoder); if (Platform.isMacOS || Platform.isLinux) { workspace = workspace ?? Directory.systemTemp.path; var file = File('$workspace/$tempFileName'); processData.file = file; - if(printStdout_) { - logHandler??('Execute Shell: ${file.path} \n ${shell.toString()}', LogType.verbose); + if (printStdout_) { + logHandler ?? + ( + 'Execute Shell: ${file.path} \n ${shell.toString()}', + LogType.verbose + ); } - if (await file.exists()) { - await file.delete(); + if (file.existsSync()) { + file.deleteSync(); } file.createSync(); - file.writeAsStringSync(shell.toString()); + file.writeAsStringSync(shell.toString(), flush: true); try { var shellExe = Platform.isMacOS ? 'zsh' : 'bash'; - processData.processValue = await Process.start(shellExe, [file.path], - workingDirectory: workspace, runInShell: false); + processData.process = await Process.start(shellExe, [file.path], + workingDirectory: workspace); } on Exception catch (e) { - logHandler??(e, LogType.error); + logHandler ?? (e, LogType.error); } } else if (Platform.isWindows) { workspace = workspace ?? Directory.systemTemp.path; var file = File('$workspace/$tempFileName'); processData.file = file; - if(printStdout_) { - logHandler??('Execute Shell: ${file.path} \n ${shell.toString()}', LogType.verbose); + if (printStdout_) { + logHandler ?? + ( + 'Execute Shell: ${file.path} \n ${shell.toString()}', + LogType.verbose + ); } if (await file.exists()) { await file.delete(); @@ -192,31 +204,42 @@ class ProcessExecutor { file.createSync(); file.writeAsStringSync(shell.toString()); try { - processData.processValue = await Process.start( - 'cmd', ['/C', file.path], + processData.process = await Process.start('cmd', ['/C', file.path], workingDirectory: workspace, runInShell: false); } on Exception catch (e) { - logHandler??(e, LogType.error); + logHandler ?? (e, LogType.error); } } else { - logHandler??('This platform not support process executor.', LogType.error); + logHandler ?? + ('This platform not support process executor.', LogType.error); } c.complete(processData); await processData.waitForExit(); } on Exception catch (e) { - logHandler??('General Exception in ProcessExecutor.start: $e', LogType.error); + logHandler ?? + ('General Exception in ProcessExecutor.start: $e', LogType.error); } return c.future; } static Future run(StringBuffer shell, - {String? workspace, bool printStdout = true, LogHandler? logHandler}) async { + {String? workspace, + bool printStdout = true, + LogHandler? logHandler}) async { var c = Completer(); workspace = workspace ?? Directory.systemTemp.path; var file = File('$workspace/$tempFileName'); - if(printStdout) { - logHandler??('---------------------------------------------------', LogType.verbose); - logHandler??('Shell Path: ${file.path} \nExecute Shell: ${shell.toString()}', LogType.verbose); + if (printStdout) { + logHandler ?? + ( + '---------------------------------------------------', + LogType.verbose + ); + logHandler ?? + ( + 'Shell Path: ${file.path} \nExecute Shell: ${shell.toString()}', + LogType.verbose + ); } ProcessResult? processResult; if (Platform.isMacOS || Platform.isLinux) { @@ -229,12 +252,15 @@ class ProcessExecutor { processResult = result; }); if (printStdout) { - logHandler??( - // ignore: prefer_interpolation_to_compose_strings - '[ProcessExecutor] Exit Code: ${processResult!.exitCode}\nResult: ${processResult!.stdout}\nError: ${processResult!.stderr}', LogType.verbose); + logHandler ?? + ( + // ignore: prefer_interpolation_to_compose_strings + '[ProcessExecutor] Exit Code: ${processResult!.exitCode}\nResult: ${processResult!.stdout}\nError: ${processResult!.stderr}', + LogType.verbose + ); } } on Exception catch (e) { - logHandler??(e, LogType.error); + logHandler ?? (e, LogType.error); } finally { file.deleteSync(); } @@ -258,7 +284,8 @@ class ProcessExecutor { file.deleteSync(); c.complete(processResult); } else { - logHandler??('This platform not support process executor.', LogType.error); + logHandler ?? + ('This platform not support process executor.', LogType.error); c.complete(null); } return c.future; @@ -271,12 +298,6 @@ class ProcessExecutor { return 'temp_${DateTime.now().microsecondsSinceEpoch}.bat'; } } - - static bool getSuccess(int exitCode) { - if (Platform.isMacOS || Platform.isLinux) return exitCode == 0; - if (Platform.isWindows) return exitCode == 1; - return false; - } } class NetStatData { @@ -395,19 +416,20 @@ Future> findProcess(String searchWord, await removeTempBat(); var c = Completer>(); var pList = []; - if(Platform.isWindows) { + if (Platform.isWindows) { var shell = StringBuffer('tasklist /fo "csv" | findstr $searchWord'); var stdout = runSlient ? await ProcessSilentExecutor.runSlientBat(shell) : await runGetStdout(shell); pList = parseProcessStd(stdout); } else { - var shell = StringBuffer('ps -A | grep \'$searchWord\' | grep -v grep | awk \'{\$2=\$3=""; print \$0}\''); + var shell = StringBuffer( + 'ps -A | grep \'$searchWord\' | grep -v grep | awk \'{\$2=\$3=""; print \$0}\''); var result = await ProcessExecutor.run(shell, printStdout: false); - if(result.exitCode == 0) { + if (result.exitCode == 0) { var procList = result.stdout.toString().split('\n'); - for(var proc in procList) { - if(proc.isNotEmpty) { + for (var proc in procList) { + if (proc.isNotEmpty) { var info = ProcessInfo(); var index = proc.indexOf(' '); info.pid = int.parse(proc.substring(0, index));