mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 07:00:43 +02:00
FEXRootFSFetcher: Add some options for automation without user intervention
Main options here are `-y` and `-a`. Passing both will allow the user to download the exact match image, use it as-is, and set the config to use the rootfs by default. Additional options `--distro-name` and `--distro-option` allows one to select a particular distro version. eg: `FEXRootFSFetcher -y -a --distro-name=ubuntu --distro-version=22.04` * Will download the first Ubuntu 22.04 compressed in the json list ** Priority of erofs or squashfs depends on order in json and what the host supports
This commit is contained in:
1 parent
ce0c24eee9
commit
a0835c95e4
1 file changed
+98
-16
@@ -1,3 +1,4 @@
|
||||
#include "OptionParser.h"
|
||||
#include "XXFileHash.h"
|
||||
|
||||
#include "Common/ArgumentLoader.h"
|
||||
@@ -15,6 +16,71 @@
|
||||
|
||||
#include <tiny-json.h>
|
||||
|
||||
namespace ArgOptions {
|
||||
bool AssumeYes = false;
|
||||
enum CompressedImageOption {
|
||||
OPTION_ASK,
|
||||
OPTION_EXTRACT,
|
||||
OPTION_ASIS,
|
||||
};
|
||||
|
||||
CompressedImageOption CompressedUsageOption {OPTION_ASK};
|
||||
|
||||
std::vector<std::string> RemainingArgs;
|
||||
|
||||
std::string DistroName{};
|
||||
std::string DistroVersion{};
|
||||
|
||||
void ParseArguments(int argc, char **argv) {
|
||||
optparse::OptionParser Parser = optparse::OptionParser()
|
||||
.description("Tool for fetching RootFS from FEXServers")
|
||||
.add_help_option(true);
|
||||
|
||||
Parser.add_option("-y", "--assume-yes")
|
||||
.action("store_true")
|
||||
.help("Assume yes to prompts");
|
||||
|
||||
Parser.add_option("-x", "--extract")
|
||||
.action("store_true")
|
||||
.help("Extract compressed image");
|
||||
|
||||
Parser.add_option("-a", "--as-is")
|
||||
.action("store_true")
|
||||
.help("Use compressed image as-is");
|
||||
|
||||
Parser.add_option("--distro-name")
|
||||
.help("Which distro name to select");
|
||||
|
||||
Parser.add_option("--distro-version")
|
||||
.help("Which distro version to select");
|
||||
|
||||
|
||||
optparse::Values Options = Parser.parse_args(argc, argv);
|
||||
|
||||
if (Options.is_set_by_user("assume_yes")) {
|
||||
AssumeYes = Options.get("assume_yes");
|
||||
}
|
||||
|
||||
if (Options.is_set_by_user("extract")) {
|
||||
CompressedUsageOption = OPTION_EXTRACT;
|
||||
}
|
||||
|
||||
if (Options.is_set_by_user("as_is")) {
|
||||
CompressedUsageOption = OPTION_ASIS;
|
||||
}
|
||||
|
||||
if (Options.is_set_by_user("distro_name")) {
|
||||
DistroName = Options["distro_name"];
|
||||
}
|
||||
|
||||
if (Options.is_set_by_user("distro_version")) {
|
||||
DistroVersion = Options["distro_version"];
|
||||
}
|
||||
|
||||
RemainingArgs = Parser.args();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Exec {
|
||||
int32_t ExecAndWaitForResponse(const char *path, char* const* args) {
|
||||
pid_t pid = fork();
|
||||
@@ -553,7 +619,7 @@ namespace Zenity {
|
||||
}
|
||||
|
||||
bool AskForConfirmation(const std::string &Question) {
|
||||
return ExecWithQuestion(Question);
|
||||
return ArgOptions::AssumeYes || ExecWithQuestion(Question);
|
||||
}
|
||||
|
||||
int32_t AskForConfirmationList(const std::string &Text, const std::vector<std::string> &Arguments) {
|
||||
@@ -720,6 +786,10 @@ namespace Zenity {
|
||||
|
||||
namespace TTY {
|
||||
bool AskForConfirmation(const std::string &Question) {
|
||||
if (ArgOptions::AssumeYes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto ToLowerInPlace = [](auto &Str) {
|
||||
std::transform(Str.begin(), Str.end(), Str.begin(),
|
||||
[](unsigned char c){ return std::tolower(c); });
|
||||
@@ -938,6 +1008,14 @@ namespace {
|
||||
|
||||
int32_t AskForDistroSelection(std::vector<WebFileFetcher::FileTargets> &Targets) {
|
||||
auto Info = DistroQuery::GetDistroInfo();
|
||||
|
||||
if (!ArgOptions::DistroName.empty()) {
|
||||
Info.DistroName = ArgOptions::DistroName;
|
||||
}
|
||||
if (!ArgOptions::DistroVersion.empty()) {
|
||||
Info.DistroVersion = ArgOptions::DistroVersion;
|
||||
}
|
||||
|
||||
return _AskForDistroSelection(Info, Targets);
|
||||
}
|
||||
|
||||
@@ -1003,16 +1081,15 @@ int main(int argc, char **argv, char **const envp) {
|
||||
// Reload the meta layer
|
||||
FEXCore::Config::ReloadMetaLayer();
|
||||
|
||||
auto Args = FEX::ArgLoader::Get();
|
||||
auto ParsedArgs = FEX::ArgLoader::GetParsedArgs();
|
||||
ArgOptions::ParseArguments(argc, argv);
|
||||
|
||||
if (Args.size()) {
|
||||
auto Res = XXFileHash::HashFile(Args[0]);
|
||||
if (ArgOptions::RemainingArgs.size()) {
|
||||
auto Res = XXFileHash::HashFile(ArgOptions::RemainingArgs[0]);
|
||||
if (Res.first) {
|
||||
fmt::print("{} has hash: {:x}\n", Args[0], Res.second);
|
||||
fmt::print("{} has hash: {:x}\n", ArgOptions::RemainingArgs[0], Res.second);
|
||||
}
|
||||
else {
|
||||
fmt::print("Couldn't generate hash for {}\n", Args[0]);
|
||||
fmt::print("Couldn't generate hash for {}\n", ArgOptions::RemainingArgs[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1107,15 +1184,25 @@ int main(int argc, char **argv, char **const envp) {
|
||||
"As-Is",
|
||||
};
|
||||
|
||||
ArgOptions::CompressedImageOption UseImageAs {ArgOptions::CompressedImageOption::OPTION_ASK};
|
||||
if (Target.Type == WebFileFetcher::FileTargets::FileType::TYPE_SQUASHFS) {
|
||||
int32_t Result{};
|
||||
if (WorkingAppsTester::Has_Unsquashfs) {
|
||||
if (WorkingAppsTester::Has_Squashfuse) {
|
||||
Result = AskForConfirmationList("Do you wish to extract the squashfs file or use it as-is?", Args);
|
||||
if (Result == 0) {
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_EXTRACT;
|
||||
}
|
||||
else if (Result == 1) {
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_ASIS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Args.pop_back();
|
||||
Result = AskForConfirmationList("Squashfuse doesn't work. Do you wish to extract the squashfs file?", Args);
|
||||
if (Result == 0) {
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_EXTRACT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1124,33 +1211,28 @@ int main(int argc, char **argv, char **const envp) {
|
||||
Result = AskForConfirmationList("Unsquashfs doesn't work. Do you want to use the squashfs file as-is?", Args);
|
||||
if (Result == 0) {
|
||||
// We removed an argument, Just change "As-Is" from 0 to 1 for later logic to work
|
||||
Result = 1;
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_ASIS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Args.erase(Args.begin());
|
||||
ExecWithInfo("Unsquashfs and squashfuse isn't working. Leaving rootfs as-is");
|
||||
Result = -1;
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_ASIS;
|
||||
}
|
||||
}
|
||||
|
||||
if (Result == -1 ||
|
||||
Result == 1) {
|
||||
// Nothing
|
||||
// As-Is
|
||||
}
|
||||
else if (Result == 0) {
|
||||
if (UseImageAs == ArgOptions::CompressedImageOption::OPTION_EXTRACT) {
|
||||
auto FolderName = filename.substr(0, filename.find_last_of('.'));
|
||||
if (UnSquash::UnsquashRootFS(RootFS, PathName, FolderName)) {
|
||||
// Remove the .sqsh suffix since we extracted to that
|
||||
filename = FolderName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (Target.Type == WebFileFetcher::FileTargets::FileType::TYPE_EROFS) {
|
||||
// Once erofs tooling is available for easy extraction, offer the same settings to extract as squashfs.
|
||||
// Currently this is unavailable, would need a mount + copy + unmount dance.
|
||||
UseImageAs = ArgOptions::CompressedImageOption::OPTION_ASIS;
|
||||
}
|
||||
|
||||
if (AskForConfirmation("Do you wish to set this RootFS as default?")) {
|
||||
|
||||
Reference in new issue
Block a user