findToolPath method
Searches for the specified tool on a remote machine using SSH and returns the path if found.
This function connects to a remote machine via SSH and attempts to find the specified tool. If the tool is found, the function will return its path. If multiple paths are found, the user will be prompted to select one. It also optionally checks for preferred paths.
Parameters:
username
: The SSH username for the remote machine.ip
: The IP address of the remote machine. Supports both IPv4 and IPv6.toolName
: The name of the tool to search for on the remote machine.toolPath
: (Optional) A specific path pattern to search within for the tool.preferredPaths
: (Optional) A list of preferred paths to prioritize if found in the search results.addHostToKnownHosts
: (Optional) Whether to add the remote host to the known hosts list. Default istrue
.
Example:
final flutterPath = await findToolPath(
username: 'user',
ip: InternetAddress('192.168.1.100'),
toolName: 'flutter',
toolPath: '*/flutter/bin/*', // Optional specific path pattern
preferredPaths: ['/usr/local/flutter/bin/flutter'], // Optional preferred paths
);
Notes:
- If
toolPath
is provided, the function will search within this specific path pattern. - If multiple paths are found, the user will be prompted to select one from the list.
- If
preferredPaths
are provided, they will be prioritized in the selection process if found. - This function uses a spinner to indicate progress and logs detailed messages during the execution.
Implementation
Future<String?> findToolPath({
required String username,
required InternetAddress ip,
required String toolName,
String? toolPath,
List<String>? preferredPaths,
bool addHostToKnownHosts = true,
}) async {
final spinner = interaction.spinner(
inProgressMessage: 'search for $toolName path on remote device.',
doneMessage: 'search for $toolName path completed',
failedMessage: 'search for $toolName path failed',
);
final searchCommand = toolPath != null
? 'find / -type f -name "$toolName" -path "$toolPath" 2>/dev/null'
: 'find / -type f -name "$toolName" 2>/dev/null';
final output = await processRunner.runCommand(
hostPlatform.sshCommand(
ipv6: ip.isIpv6,
sshTarget: ip.sshTarget(username),
command: searchCommand,
addHostToKnownHosts: addHostToKnownHosts,
),
timeout: const Duration(seconds: 30),
throwOnError: false,
parseResult: (runResult) {
final output = runResult.stdout.trim();
if (runResult.exitCode != 0 && output.isEmpty) {
logger.spaces();
return null;
}
return output;
},
parseFail: (e, s) {
logger.detail(
'Something went wrong while trying to find $toolName. \n $e \n $s',
);
logger.spaces();
return null;
},
spinner: spinner,
label: 'Find $toolName',
logger: logger,
);
logger.detail('Find $toolName output: $output');
logger.spaces();
if (output == null) return null;
final outputLinesLength = output.split('\n').length;
final isOutputMultipleLines = outputLinesLength > 1;
if (!isOutputMultipleLines) {
logger.info('We found $toolName in "$output" in the remote machine. ');
final toolPathConfirmation = interaction.confirm(
'Do you want to use this path?',
defaultValue: true, // this is optional
);
return toolPathConfirmation ? output : null;
} else {
logger.info('We found multiple $toolName paths in the remote machine. ');
final outputLines = output
.split('\n')
.map((e) => e.trim())
.toList()
.sublist(0, min(2, outputLinesLength));
if (preferredPaths != null) {
final preferredPathsSet = preferredPaths.toSet();
final preferredPathsInOutput = outputLines
.where(
(line) => preferredPathsSet.any(
(path) => line.contains(path),
),
)
.toList();
if (preferredPathsInOutput.isNotEmpty) {
if (preferredPathsInOutput.length == 1) {
return preferredPathsInOutput.first;
}
return interaction.select(
'Please select the path of $toolName you want to use.',
options: preferredPathsInOutput,
);
}
}
return interaction.select(
'Please select the path of $toolName you want to use.',
options: outputLines,
);
}
}